[
  {
    "path": "README.md",
    "content": "# Recipes with Angular.js Example\n\nExamples to accompany the book\n[Recipes with Angular.js](http://leanpub.com/recipes-with-angular-js).\n\nIf you have questions or comments, open an issue or [email me](fdietz@gmail.com).\n\nMost examples are using [angular-seed](https://github.com/angular/angular-seed) or [angular-express-seed](https://github.com/btford/angular-express-seed) as a bootstrap.\n"
  },
  {
    "path": "chapter1/recipe1/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter1/recipe1/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app>\n    <p>This is your first angular expression {{1 + 2}}</p>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter1/recipe1/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter1/recipe2/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter1/recipe2/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app>\n    Enter your name: <input type=\"text\" ng-model=\"name\">\n    <p>Hello {{name}}!</p>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter1/recipe2/jquery_example.html",
    "content": "<html>\n  <head>\n    <script src=\"http://code.jquery.com/jquery.min.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body>\n    Enter your name: <input type=\"text\"></input>\n    <p id=\"name\"></p>\n\n    <script>\n      $(document).ready(function() {\n        $(\"input\").keypress(function() {\n          $(\"#name\").text($(this).val());\n        });  \n      });\n    </script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "chapter1/recipe2/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter1/recipe3/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter1/recipe3/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app>\n    <div ng-controller=\"MyCtrl\">\n      <button class=\"btn\" ng-click=\"toggle()\">Toggle</button>\n      <p ng-show=\"visible\">Hello World!</p>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter1/recipe3/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter1/recipe3/js/app.js",
    "content": "function MyCtrl($scope) {\n  $scope.visible = true;\n\n  $scope.toggle = function() {\n    $scope.visible = !$scope.visible;\n  };\n}"
  },
  {
    "path": "chapter1/recipe4/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter1/recipe4/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app>\n    Enter your name: <input type=\"text\" ng-model=\"name\">\n    <p>Hello {{name | uppercase | lowercase }}!</p>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter1/recipe4/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter1/recipe5/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter1/recipe5/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <label for=\"checkbox\"><input id=\"checkbox\" type=\"checkbox\" ng-model=\"visible\">Toggle me</label>\n    <div show=\"visible\">\n      <p>Hello World</p>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter1/recipe5/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter1/recipe5/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.directive(\"show\", function() {\n  return {\n    link: function(scope, element, attrs) {\n      scope.$watch(attrs.show, function(value){\n        element.css('display', value ? '' : 'none');\n      });\n    }\n  };\n});\n"
  },
  {
    "path": "chapter10/recipe1/contacts/README.md",
    "content": "# Angular Express Seed\n\nStart an awesome app with AngularJS on the front, Express + Node on the back. This project is an\napplication skeleton for a typical [AngularJS](http://angularjs.org/) web app for those who want\nto use Node to serve their app.\n\nThe seed contains angular libraries, test libraries and a bunch of scripts all preconfigured for\ninstant web development gratification. Just clone the repo (or download the zip/tarball) and\nyou're ready to develop your application.\n\nThe seed app shows how to wire together Angular client-side components with Express on the server.\nIt also illustrates writing angular partials/views with the Jade templating library.\n\n_Note: Although Jade supports interpolation, you should be doing that mostly on the client. Mixing\nserver and browser templating will convolute your app. Instead, use Jade as a syntactic sugar for\nHTML, and let AngularJS take care of interpolation on the browser side._\n\n## How to use angular-express-seed\n\nClone the angular-express-seed repository, run `npm install` to grab the dependencies, and start hacking!\n\n### Running the app\n\nRuns like a typical express app:\n\n    node app.js\n\n### Running tests\n\nComing soon!\n\n### Receiving updates from upstream\n\nJust fetch the changes and merge them into your project with git.\n\n\n## Directory Layout\n    \n    app.js              --> app config\n    package.json        --> for npm\n    public/             --> all of the files to be used in on the client side\n      css/              --> css files\n        app.css         --> default stylesheet\n      img/              --> image files\n      js/               --> javascript files\n        app.js          --> declare top-level app module\n        controllers.js  --> application controllers\n        directives.js   --> custom angular directives\n        filters.js      --> custom angular filters\n        services.js     --> custom angular services\n        lib/            --> angular and 3rd party JavaScript libraries\n          angular/\n            angular.js            --> the latest angular js\n            angular.min.js        --> the latest minified angular js\n            angular-*.js          --> angular add-on modules\n            version.txt           --> version number\n    routes/\n      api.js            --> route for serving JSON\n      index.js          --> route for serving HTML pages and partials\n    views/\n      index.jade        --> main page for app\n      layout.jade       --> doctype, title, head boilerplate\n      partials/         --> angular view partials (partial jade templates)\n        partial1.jade\n        partial2.jade\n\n\n\n## Example App\n\nA simple [blog](https://github.com/btford/angular-express-blog) based on this seed.\n\n\n## Contact\n\nFor more information on AngularJS please check out http://angularjs.org/\nFor more on Express and Jade, http://expressjs.com/ and http://jade-lang.com/ are\nyour friends.\n"
  },
  {
    "path": "chapter10/recipe1/contacts/app.js",
    "content": "var express = require('express'),\n  routes = require('./routes'),\n  api = require('./routes/api');\n\nvar app = module.exports = express();\n\napp.configure(function(){\n  app.set('views', __dirname + '/views');\n  app.set('view engine', 'jade');\n  app.use(express.bodyParser());\n  app.use(express.methodOverride());\n  app.use(express.static(__dirname + '/public'));\n  app.use(app.router);\n});\n\napp.configure('development', function(){\n  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));\n});\n\napp.configure('production', function(){\n  app.use(express.errorHandler());\n});\n\napp.get('/', routes.index);\napp.get('/partials/:name', routes.partials);\n\napp.get('/api/contacts', api.contacts);\napp.get('/api/contacts/:id', api.contact);\napp.post('/api/contacts', api.createContact);\napp.put('/api/contacts/:id', api.updateContact);\napp.delete('/api/contacts/:id', api.destroyContact);\n\napp.get('*', routes.index);\n\napp.listen(3000, function(){\n  console.log(\"Express server listening on port %d in %s mode\", this.address().port, app.settings.env);\n});\n"
  },
  {
    "path": "chapter10/recipe1/contacts/package.json",
    "content": "{\n    \"name\": \"contacts\"\n  , \"version\": \"0.0.1\"\n  , \"private\": true\n  , \"dependencies\": {\n      \"express\": \">= 3.1.0\"\n    , \"jade\": \">= 0.28.1\"\n    , \"mongoose\": \">= 3.5.6\"\n  }\n}"
  },
  {
    "path": "chapter10/recipe1/contacts/public/css/app.css",
    "content": "body {\n  padding-top: 50px;\n}\n\nfooter {\n  margin-top: 20px;\n}"
  },
  {
    "path": "chapter10/recipe1/contacts/public/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.3.0\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover,\na:focus {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover,\na.muted:focus {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover,\na.text-warning:focus {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover,\na.text-error:focus {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover,\na.text-info:focus {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover,\na.text-success:focus {\n  color: #356635;\n}\n\n.text-left {\n  text-align: left;\n}\n\n.text-right {\n  text-align: right;\n}\n\n.text-center {\n  text-align: center;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  *display: inline;\n  padding-right: 5px;\n  padding-left: 5px;\n  *zoom: 1;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 17.5px;\n  font-weight: 300;\n  line-height: 1.25;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  display: inline-block;\n  margin-bottom: 10px;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu,\n.input-append .popover,\n.input-prepend .popover {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child,\n.table-bordered tbody:first-child tr:first-child > th:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child,\n.table-bordered tbody:first-child tr:first-child > th:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tbody:last-child tr:last-child > th:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > th:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tbody:last-child tr:last-child > th:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > th:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover > td,\n.table-hover tbody tr:hover > th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success > td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error > td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning > td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info > td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover > td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover > td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover > td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover > td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/focus/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:focus > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > li > a:focus > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:focus > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"],\n.dropdown-submenu:focus > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  width: 16px;\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu > li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus,\n.dropdown-submenu:hover > a,\n.dropdown-submenu:focus > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  color: #999999;\n}\n\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover,\n.close:focus {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #cccccc;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #b3b3b3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:focus,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover,\n.btn:focus {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:focus,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:focus,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:focus,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:focus,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:focus,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:focus,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover,\n.btn-link:focus {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover,\n.btn-link[disabled]:focus {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.btn-mini .caret,\n.btn-small .caret {\n  margin-top: 8px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover,\n.nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover,\n.nav-list > .active > a:focus {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover,\n.nav-tabs > li > a:focus {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover,\n.nav-tabs > .active > a:focus {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover,\n.nav-pills > .active > a:focus {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover,\n.nav-tabs.nav-stacked > li > a:focus {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret,\n.nav .dropdown-toggle:focus .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover,\n.nav > .dropdown.active > a:focus {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover,\n.nav > li.dropdown.open.active > a:focus {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret,\n.nav li.dropdown.open a:focus .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover,\n.tabs-stacked .open > a:focus {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover,\n.tabs-below > .nav-tabs > li > a:focus {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover,\n.tabs-below > .nav-tabs > .active > a:focus {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover,\n.tabs-left > .nav-tabs > li > a:focus {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover,\n.tabs-left > .nav-tabs .active > a:focus {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover,\n.tabs-right > .nav-tabs > li > a:focus {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover,\n.tabs-right > .nav-tabs .active > a:focus {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover,\n.nav > .disabled > a:focus {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover,\n.navbar .brand:focus {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover,\n.navbar-link:focus {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn,\n.navbar .input-prepend .btn-group,\n.navbar .input-append .btn-group {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:focus,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret,\n.navbar .nav li.dropdown > a:focus .caret {\n  border-top-color: #333333;\n  border-bottom-color: #333333;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover,\n.navbar-inverse .brand:focus,\n.navbar-inverse .nav > li > a:focus {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover,\n.navbar-inverse .navbar-link:focus {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret,\n.navbar-inverse .nav li.dropdown > a:focus .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:focus,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > li > a:focus,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover,\n.pagination ul > .disabled > a:focus {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover,\n.pager li > a:focus {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  font-size: 11px;\n  line-height: 1.4;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  padding: 5px 0;\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  padding: 0 5px;\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  padding: 5px 0;\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  padding: 0 5px;\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  max-width: 276px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-title:empty {\n  display: none;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover,\na.thumbnail:focus {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media > .pull-left {\n  margin-right: 10px;\n}\n\n.media > .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.label:focus,\na.badge:hover,\na.badge:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover,\n.carousel-control:focus {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-indicators {\n  position: absolute;\n  top: 15px;\n  right: 15px;\n  z-index: 5;\n  margin: 0;\n  list-style: none;\n}\n\n.carousel-indicators li {\n  display: block;\n  float: left;\n  width: 10px;\n  height: 10px;\n  margin-left: 5px;\n  text-indent: -999px;\n  background-color: #ccc;\n  background-color: rgba(255, 255, 255, 0.25);\n  border-radius: 5px;\n}\n\n.carousel-indicators .active {\n  background-color: #fff;\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/app.js",
    "content": "'use strict';\n\n// Declare app level module which depends on filters, and services\nvar app = angular.module('myApp', [\"ngResource\"]).\n  config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {\n    $locationProvider.html5Mode(true);\n    $routeProvider\n      .when(\"/contacts\", { templateUrl: \"partials/index.jade\", controller: \"ContactsIndexCtrl\" })\n      .when(\"/contacts/new\", { templateUrl: \"partials/edit.jade\", controller: \"ContactsEditCtrl\" })\n      .when(\"/contacts/:id\", { templateUrl: \"partials/show.jade\", controller: \"ContactsShowCtrl\" })\n      .when(\"/contacts/:id/edit\", { templateUrl: \"partials/edit.jade\", controller: \"ContactsEditCtrl\" })\n      .otherwise({ redirectTo: \"/contacts\" });\n  }]);"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/controllers/ContactsEditCtrl.js",
    "content": "app.controller(\"ContactsEditCtrl\", function($scope, $routeParams, $location, Contact) {\n\n  if ($routeParams.id) {\n    $scope.contact = Contact.show({ id: $routeParams.id });\n  } else {\n    $scope.contact = new Contact();\n  }\n\n  $scope.submit = function() {\n    console.log(\"submit\")\n\n    function success(response) {\n      console.log(\"success\", response)\n      $location.path(\"/contacts\");\n    }\n\n    function failure(response) {\n      console.log(\"failure\", response)\n\n      _.each(response.data, function(errors, key) {\n        if (errors.length > 0) {\n          _.each(errors, function(e) {\n            $scope.form[key].$dirty = true;\n            $scope.form[key].$setValidity(e, false);\n          });\n        }\n      });\n    }\n\n    if ($routeParams.id) {\n      Contact.update($scope.contact, success, failure);\n    } else {\n      Contact.create($scope.contact, success, failure);\n    }\n\n  };\n\n  $scope.cancel = function() {\n    $location.path(\"/contacts/\"+$scope.contact._id);\n  };\n\n  $scope.errorClass = function(name) {\n    var s = $scope.form[name];\n    return s.$invalid && s.$dirty ? \"error\" : \"\";\n  };\n\n  $scope.errorMessage = function(name) {\n    var s = $scope.form[name].$error;\n    result = [];\n    _.each(s, function(key, value) {\n      result.push(value);\n    });\n    return result.join(\", \");\n  };\n});"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/controllers/ContactsIndexCtrl.js",
    "content": "app.controller(\"ContactsIndexCtrl\", function($scope, $location, Contact) {\n  $scope.contacts = Contact.index();\n\n  $scope.new = function() {\n    $location.path(\"/contacts/new\");\n  };\n});"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/controllers/ContactsShowCtrl.js",
    "content": "app.controller(\"ContactsShowCtrl\", function($scope, $routeParams, Contact) {\n  $scope.contact = Contact.show({ id: $routeParams.id });\n});"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/controllers/MainCtrl.js",
    "content": "app.controller(\"MainCtrl\", function($scope) {\n});"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/controllers.js",
    "content": "'use strict';"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/directives.js",
    "content": "'use strict';\n\n/* Directives */\n\n\nangular.module('myApp.directives', []).\n  directive('appVersion', ['version', function(version) {\n    return function(scope, elm, attrs) {\n      elm.text(version);\n    };\n  }]);\n"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/filters.js",
    "content": "'use strict';\n\n/* Filters */\n\nangular.module('myApp.filters', []).\n  filter('interpolate', ['version', function(version) {\n    return function(text) {\n      return String(text).replace(/\\%VERSION\\%/mg, version);\n    }\n  }]);\n"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/lib/angular/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngCookies\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookies\n   * @requires $browser\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from\n   * this object, new cookies are created/deleted at the end of current $eval.\n   *\n   * @example\n   */\n   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for(name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            if (angular.isDefined(lastCookies[name])) {\n              cookies[name] = lastCookies[name];\n            } else {\n              delete cookies[name];\n            }\n          } else if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated){\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   * @example\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#get\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          return angular.fromJson($cookies[key]);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#put\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#remove\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/lib/angular/angular-loader.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n\n(\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n'use strict';\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n)(window);\n\n/**\n * Closure compiler type information\n *\n * @typedef { {\n *   requires: !Array.<string>,\n *   invokeQueue: !Array.<Array.<*>>,\n *\n *   service: function(string, Function):angular.Module,\n *   factory: function(string, Function):angular.Module,\n *   value: function(string, *):angular.Module,\n *\n *   filter: function(string, Function):angular.Module,\n *\n *   init: function(Function):angular.Module\n * } }\n */\nangular.Module;\n\n"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/lib/angular/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n /**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` – {string} – The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` – {object=} – Optional set of pre-bound parameters for this action.\n *   - isArray – {boolean=} – If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n  /**\n   * We need our custom mehtod because encodeURIComponent is too aggressive and doesn't follow\n   * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n   * segments:\n   *    segment       = *pchar\n   *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n   *    pct-encoded   = \"%\" HEXDIG HEXDIG\n   *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n   *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n   *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n   */\n  function encodeUriSegment(val) {\n    return encodeUriQuery(val, true).\n      replace(/%26/gi, '&').\n      replace(/%3D/gi, '=').\n      replace(/%2B/gi, '+');\n  }\n\n\n  /**\n   * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n   * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n   * encoded per http://tools.ietf.org/html/rfc3986:\n   *    query       = *( pchar / \"/\" / \"?\" )\n   *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n   *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n   *    pct-encoded   = \"%\" HEXDIG HEXDIG\n   *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n   *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n   */\n  function encodeUriQuery(val, pctEncodeSpaces) {\n    return encodeURIComponent(val).\n      replace(/%40/gi, '@').\n      replace(/%3A/gi, ':').\n      replace(/%24/g, '$').\n      replace(/%2C/gi, ',').\n      replace((pctEncodeSpaces ? null : /%20/g), '+');\n  }\n\n  function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"/?:\" + urlParam + \"(\\\\W)\", \"g\"), '$1');\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.bind = function(additionalParamDefaults){\n          return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/lib/angular/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             '<p style=\"color:blue\">an html\\n' +\n             '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n             'snippet</p>';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n          Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n           <table>\n             <tr>\n               <td>Filter</td>\n               <td>Source</td>\n               <td>Rendered</td>\n             </tr>\n             <tr id=\"html-filter\">\n               <td>html filter</td>\n               <td>\n                 <pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre>\n               </td>\n               <td>\n                 <div ng-bind-html=\"snippet\"></div>\n               </td>\n             </tr>\n             <tr id=\"escaped-html\">\n               <td>no filter</td>\n               <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind=\"snippet\"></div></td>\n             </tr>\n             <tr id=\"html-unsafe-filter\">\n               <td>unsafe html filter</td>\n               <td><pre>&lt;div ng-bind-html-unsafe=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind-html-unsafe=\"snippet\"></div></td>\n             </tr>\n           </table>\n         </div>\n     </doc:source>\n     <doc:scenario>\n       it('should sanitize the html snippet ', function() {\n         expect(using('#html-filter').element('div').html()).\n           toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n       });\n\n       it('should escape snippet without any filter', function() {\n         expect(using('#escaped-html').element('div').html()).\n           toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n                \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n                \"snippet&lt;/p&gt;\");\n       });\n\n       it('should inline raw snippet if filtered as unsafe', function() {\n         expect(using('#html-unsafe-filter').element(\"div\").html()).\n           toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n                \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n                \"snippet</p>\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new <b>text</b>');\n         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');\n         expect(using('#escaped-html').element('div').html()).toBe(\"new &lt;b&gt;text&lt;/b&gt;\");\n         expect(using('#html-unsafe-filter').binding(\"snippet\")).toBe('new <b>text</b>');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar $sanitize = function(html) {\n  var buf = [];\n    htmlParser(html, htmlSanitizeWriter(buf));\n    return buf.join('');\n};\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP = /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  URI_REGEXP = /^((ftp|https?):\\/\\/|mailto:|#)/,\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g; // Match everything outside of normal chars and \" (quote character)\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,aside,\" +\n        \"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,\" +\n        \"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,bdi,bdo,\" +\n        \"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,\" +\n        \"span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        index = html.indexOf(\"-->\");\n\n        if ( index >= 0 ) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'), function(all, text){\n        text = text.\n          replace(COMMENT_REGEXP, \"$1\").\n          replace(CDATA_REGEXP, \"$1\");\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n\n        return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw \"Parse Error: \" + html;\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {\n      var value = doubleQuotedValue\n        || singleQoutedValue\n        || unqoutedValue\n        || '';\n\n      attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nvar hiddenPre=document.createElement(\"pre\");\nfunction decodeEntities(value) {\n  hiddenPre.innerHTML=value.replace(/</g,\"&lt;\");\n  return hiddenPre.innerText || hiddenPre.textContent || '';\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] == true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] == true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).value('$sanitize', $sanitize);\n\n/**\n * @ngdoc directive\n * @name ngSanitize.directive:ngBindHtml\n *\n * @description\n * Creates a binding that will sanitize the result of evaluating the `expression` with the\n * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n */\nangular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);\n    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {\n      value = $sanitize(value);\n      element.html(value || '');\n    });\n  };\n}]);\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n *   plain email address links.\n *\n * @param {string} text Input text.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should linkify the snippet with urls', function() {\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('Pretty text with some links:&#10;' +\n                '<a href=\"http://angularjs.org/\">http://angularjs.org/</a>,&#10;' +\n                '<a href=\"mailto:us@somewhere.org\">us@somewhere.org</a>,&#10;' +\n                '<a href=\"mailto:another@somewhere.org\">another@somewhere.org</a>,&#10;' +\n                'and one more: <a href=\"ftp://127.0.0.1/\">ftp://127.0.0.1/</a>.');\n       });\n\n       it ('should not linkify snippet without the linky filter', function() {\n         expect(using('#escaped-html').binding('snippet')).\n           toBe(\"Pretty text with some links:\\n\" +\n                \"http://angularjs.org/,\\n\" +\n                \"mailto:us@somewhere.org,\\n\" +\n                \"another@somewhere.org,\\n\" +\n                \"and one more: ftp://127.0.0.1/.\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new http://link.');\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('new <a href=\"http://link\">http://link</a>.');\n         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', function() {\n  var LINKY_URL_REGEXP = /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s\\.\\;\\,\\(\\)\\{\\}\\<\\>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    // TODO(vojta): use $sanitize instead\n    var writer = htmlSanitizeWriter(html);\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      writer.chars(raw.substr(0, i));\n      writer.start('a', {href:url});\n      writer.chars(match[0].replace(MAILTO_REGEXP, ''));\n      writer.end('a');\n      raw = raw.substring(i + match[0].length);\n    }\n    writer.chars(raw);\n    return html.join('');\n  };\n});\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/lib/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) !== '$' && !isFunction(o1[key]) && !equals(o1[key], o2[key])) {\n            return false;\n          }\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] && key.charAt(0) !== '$' && !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.3',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 3,\n  codeName: 'bouncy-thunder'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular privides an additional method to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeName != '#text')\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes;\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    return element.nextSibling;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key, path)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $locaiton.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n          if (lastCookies.length > 20) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because too many cookies \" +\n              \"were already set (\" + lastCookies.length + \" > 20 )\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n     var linkFns = [],\n         nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n     for(var i = 0; i < nodeList.length; i++) {\n       attrs = new Attributes();\n\n       // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n       directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n       nodeLinkFn = (directives.length)\n           ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n           : null;\n\n       childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n           ? null\n           : compileNodes(nodeList[i].childNodes,\n                nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n       linkFns.push(nodeLinkFn);\n       linkFns.push(childLinkFn);\n       linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n     }\n\n     // return a linking function if we have found anything, null otherwise\n     return linkFnFound ? compositeLinkFn : null;\n\n     function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n       var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn;\n\n       for(var i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n         node = nodeList[n];\n         nodeLinkFn = linkFns[i++];\n         childLinkFn = linkFns[i++];\n\n         if (nodeLinkFn) {\n           if (nodeLinkFn.scope) {\n             childScope = scope.$new(isObject(nodeLinkFn.scope));\n             jqLite(node).data('$scope', childScope);\n           } else {\n             childScope = scope;\n           }\n           childTranscludeFn = nodeLinkFn.transclude;\n           if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n             nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                 (function(transcludeFn) {\n                   return function(cloneFn) {\n                     var transcludeScope = scope.$new();\n\n                     return transcludeFn(transcludeScope, cloneFn).\n                         bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n             );\n           } else {\n             nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n           }\n         } else if (childLinkFn) {\n           childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n         }\n       }\n     }\n   }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite('<!-- ' + directiveName + ': ' + templateAttrs[directiveName]  + ' -->');\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler}\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programing what `try`, `catch` and `throw` keywords are to synchronous programing.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exacly match the\n   *    route definition.\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var matcher = switchRouteMatcher,\n        forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n      var regex = '^' + when.replace(/([\\.\\\\\\(\\)\\^\\$])/g, \"\\\\$1\") + '$',\n          params = [],\n          dst = {};\n      forEach(when.split(/\\W/), function(param) {\n        if (param) {\n          var paramRegExp = new RegExp(\":\" + param + \"([\\\\W])\");\n          if (regex.match(paramRegExp)) {\n            regex = regex.replace(paramRegExp, \"([^\\\\/]*)$1\");\n            params.push(param);\n          }\n        }\n      });\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = matcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             this.greeting = this.salutation + ' ' + this.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { counter = counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             counter = counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        if ($rootScope == this) return; // we can't remove the root node;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBacked\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with status\n     *       // code outside of the <200, 400) range\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n          return false; // Needed for opera\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containg forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `REQUIRED`, `URL` or `EMAIL`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.REQUIRED\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.REQUIRED = {{!!myForm.$error.REQUIRED}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            collectionLength = size(collection, true),\n            childScope,\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            key, value, // key/value of iteration\n            array, last,       // last object information {scope, element, index}\n            cursor = iterStartElement;     // current position of the node\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (collectionLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  compile: function(element, attr) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        cases = {};\n\n    element.data(NG_SWITCH, cases);\n    return function(scope, element){\n      var selectedTransclude,\n          selectedElement,\n          selectedScope;\n\n      scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n        if (selectedElement) {\n          selectedScope.$destroy();\n          selectedElement.remove();\n          selectedElement = selectedScope = null;\n        }\n        if ((selectedTransclude = cases['!' + value] || cases['?'])) {\n          scope.$eval(attr.change);\n          selectedScope = scope.$new();\n          selectedTransclude(selectedScope, function(caseElement) {\n            selectedElement = caseElement;\n            element.append(caseElement);\n          });\n        }\n      });\n    };\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  compile: function(element, attrs, transclude) {\n    var cases = element.inheritedData(NG_SWITCH);\n    assertArg(cases);\n    cases['!' + attrs.ngSwitchWhen] = transclude;\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  compile: function(element, attrs, transclude) {\n    var cases = element.inheritedData(NG_SWITCH);\n    assertArg(cases);\n    cases['?'] = transclude;\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.template = {{$route.current.template}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.children(), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.children(), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/lib/angular/version.txt",
    "content": "1.0.3\n"
  },
  {
    "path": "chapter10/recipe1/contacts/public/js/services.js",
    "content": "'use strict';\n\napp.factory(\"Contact\", function($resource, $http) {\n  var resource = $resource(\"/api/contacts/:id\", { id: \"@_id\" },\n    {\n      'create':  { method: 'POST' },\n      'index':   { method: 'GET', isArray: true },\n      'show':    { method: 'GET', isArray: false },\n      'update':  { method: 'PUT' },\n      'destroy': { method: 'DELETE' }\n    }\n  );\n\n  return resource;\n});"
  },
  {
    "path": "chapter10/recipe1/contacts/routes/api.js",
    "content": "var mongoose = require('mongoose');\nmongoose.connect('mongodb://localhost/contacts_database');\n\nvar contactSchema = mongoose.Schema({ firstname: 'string', lastname: 'string', age: 'number' });\nvar Contact = mongoose.model('Contact', contactSchema);\n\nexports.contacts = function(req, res) {\n  Contact.find({}, function(err, obj) {\n    res.json(obj)\n  });\n};\n\nexports.contact = function(req, res) {\n  Contact.findOne({ _id: req.params.id }, function(err, obj) {\n    res.json(obj);\n  });\n};\n\nexports.createContact = function(req, res) {\n  var contact = new Contact(req.body);\n  contact.save();\n  res.json(req.body);\n};\n\nexports.updateContact = function(req, res) {\n  Contact.findByIdAndUpdate(req.params.id, {\n    $set: { firstname: req.body.firstname, lastname: req.body.lastname, age: req.body.age }\n  }, { upsert: true },\n  function(err, obj) {\n    return res.json(true);\n  });\n};\n\nexports.destroyContact = function(req, res) {\n  Contact.remove({ _id: req.params.id }, function(err) {\n    res.json(true);\n  });\n};"
  },
  {
    "path": "chapter10/recipe1/contacts/routes/index.js",
    "content": "exports.index = function(req, res){\n  res.render('layout');\n};\n\nexports.partials = function (req, res) {\n  var name = req.params.name;\n  res.render('partials/' + name);\n};"
  },
  {
    "path": "chapter10/recipe1/contacts/views/layout.jade",
    "content": "!!!\nhtml(ng-app=\"myApp\")\n  head\n    meta(charset='utf8')\n    base(href='/')\n    title Angular Express Seed App\n    link(rel='stylesheet', href='/css/bootstrap.css')\n    link(rel='stylesheet', href='/css/app.css')\n  body\n    div.navbar.navbar-fixed-top\n      div.navbar-inner\n        div.container\n          a.brand(href=\"/\") Contacts\n\n    div.container\n      div.row\n        div.span12\n          div(ng-controller='MainCtrl')\n            ng-view\n\n      div.footer\n        p &copy; Company 2012\n\n    script(src='js/lib/angular/angular.js')\n    script(src='js/lib/angular/angular-resource.js')\n    script(src='js/app.js')\n    script(src='js/services.js')\n    script(src='js/controllers/ContactsEditCtrl.js')\n    script(src='js/controllers/ContactsIndexCtrl.js')\n    script(src='js/controllers/ContactsShowCtrl.js')\n    script(src='js/controllers/MainCtrl.js')\n    script(src='js/filters.js')\n    script(src='js/directives.js')\n"
  },
  {
    "path": "chapter10/recipe1/contacts/views/partials/.gitignore",
    "content": ""
  },
  {
    "path": "chapter10/recipe1/contacts/views/partials/edit.jade",
    "content": "h3 Contact Details\n\nform.form-horizontal(name=\"form\", ng-submit=\"submit()\", novalidate)\n  .control-group(ng-class=\"errorClass('firstname')\")\n    label.control-label(for=\"firstname\") First Name\n    .controls\n      input(ng-model=\"contact.firstname\", type=\"text\", name=\"firstname\", placeholder=\"First Name\", require, autofocus)\n\n  .control-group(ng-class=\"errorClass('lastname')\")\n    label.control-label(for=\"lastname\") Last Name\n    .controls\n      input(ng-model=\"contact.lastname\", type=\"text\", name=\"lastname\", placeholder=\"Last Name\", require)\n\n  .control-group(ng-class=\"errorClass('age')\")\n    label.control-label(for=\"age\") Age\n    .controls\n      input(ng-model=\"contact.age\", type=\"text\", name=\"age\", placeholder=\"Age Name\", require)\n\n  .control-group\n    .controls\n      a.btn(ng-click=\"cancel()\") Cancel\n      button.btn.btn-success(type=\"submit\") Save\n\na(href=\"/contacts/{{contact.id}}\") Back"
  },
  {
    "path": "chapter10/recipe1/contacts/views/partials/index.jade",
    "content": "h3 Contacts\n\ntable.table.table-striped\n  thead\n    td Id\n    td First Name\n    td Last Name\n    td Age\n    td Actions\n  tbody\n    tr(ng-repeat=\"contact in contacts\")\n      td {{contact._id}}\n      td {{contact.firstname}}\n      td {{contact.lastname}}\n      td {{contact.age}}\n      td\n        a(href=\"/contacts/{{contact._id}}\") Show\n         |\n        a(href=\"/contacts/{{contact._id}}/edit\") Edit\n\nbutton.btn.btn-success(ng-click=\"new()\") New Contact\n"
  },
  {
    "path": "chapter10/recipe1/contacts/views/partials/show.jade",
    "content": "h3 Contact Details\n\ndiv\n  h5 First Name\n  {{contact.firstname}}\n\n  h5 Last Name\n  {{contact.lastname}}\n\n  h5 Age\n  {{contact.age}}\n\nhr\n\ndiv\n  a(href=\"/contacts\") Back\n  |\n  a(href=\"/contacts/{{contact._id}}/edit\") Edit"
  },
  {
    "path": "chapter2/recipe1/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter2/recipe1/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app>\n    <div ng-controller=\"MyCtrl\">\n      <p>{{value}}</p>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter2/recipe1/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter2/recipe1/js/app.js",
    "content": "function MyCtrl($scope) {\n  $scope.value = \"some value\";\n}"
  },
  {
    "path": "chapter2/recipe2/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter2/recipe2/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app>\n    <div ng-controller=\"MyCtrl\">\n      <p ng-init=\"incrementValue(5)\">{{value}}</p>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter2/recipe2/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter2/recipe2/js/app.js",
    "content": "function MyCtrl($scope) {\n  $scope.value = 1;\n\n  $scope.incrementValue = function(value) {\n    $scope.value += 1;\n  };\n}"
  },
  {
    "path": "chapter2/recipe3/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter2/recipe3/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app>\n    <div ng-controller=\"MyCtrl\">\n      <p>{{getIncrementedValue()}}</p>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter2/recipe3/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter2/recipe3/js/app.js",
    "content": "function MyCtrl($scope) {\n  $scope.value = 1;\n\n  $scope.getIncrementedValue = function() {\n    return $scope.value + 1;\n  };\n}"
  },
  {
    "path": "chapter2/recipe4/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter2/recipe4/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app>\n    <div ng-controller=\"MyCtrl\">\n      <input type=\"text\" ng-model=\"name\" placeholder=\"Enter your name\">\n      <p>{{greeting}}</p>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter2/recipe4/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter2/recipe4/js/app.js",
    "content": "function MyCtrl($scope) {\n  $scope.name = \"\";\n\n  $scope.$watch(\"name\", function(newValue, oldValue) {\n    if (newValue.length > 0) {\n      $scope.greeting = \"Greetings \" + newValue;\n    }\n  });\n}"
  },
  {
    "path": "chapter2/recipe5/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter2/recipe5/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n    <style>\n      .nested {\n        border: 1px solid red;\n        margin-left: 2em;\n        padding: 1em;\n      }\n    </style>\n  </head>\n  <body ng-app=\"MyApp\">\n    <div ng-controller=\"MyCtrl\">\n      <label>Primitive</label>\n      <input type=\"text\" ng-model=\"name\">\n\n      <label>Object</label>\n      <input type=\"text\" ng-model=\"user.name\">\n\n      <div class=\"nested\" ng-controller=\"MyNestedCtrl\">\n        <label>Primitive</label>\n        <input type=\"text\" ng-model=\"name\">\n\n        <label>Primitive with explicit $parent reference</label>\n        <input type=\"text\" ng-model=\"$parent.name\">\n\n        <label>Object</label>\n        <input type=\"text\" ng-model=\"user.name\">\n      </div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter2/recipe5/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter2/recipe5/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.controller(\"MyCtrl\", function($scope) {\n  $scope.name = \"Peter\";\n  $scope.user = {\n    name: \"Parker\"\n  };\n});\n\napp.controller(\"MyNestedCtrl\", function($scope) {\n});"
  },
  {
    "path": "chapter2/recipe6/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter2/recipe6/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n    <style>\n      .nested {\n        border: 1px solid red;\n        margin-left: 2em;\n        padding: 1em;\n      }\n    </style>\n  </head>\n  <body ng-app=\"MyApp\">\n    <div ng-controller=\"MyCtrl\">\n      <ul ng-repeat=\"user in users\">\n        <li>{{user}}</li>\n      </ul>\n      <div class=\"nested\" ng-controller=\"AnotherCtrl\">\n        First user: {{firstUser}}\n      </div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter2/recipe6/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter2/recipe6/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.factory(\"UserService\", function() {\n  var users = [\"Peter\", \"Daniel\", \"Nina\"];\n\n  return {\n    all: function() {\n      return users;\n    },\n    first: function() {\n      return users[0];\n    }\n  };\n});\n\napp.controller(\"MyCtrl\", function($scope, UserService) {\n  $scope.users = UserService.all();\n});\n\napp.controller(\"AnotherCtrl\", function($scope, UserService) {\n  $scope.firstUser = UserService.first();\n});"
  },
  {
    "path": "chapter2/recipe7/README.md",
    "content": "# angular-seed — the seed for AngularJS apps\n\nThis project is an application skeleton for a typical [AngularJS](http://angularjs.org/) web app.\nYou can use it to quickly bootstrap your angular webapp projects and dev environment for these\nprojects.\n\nThe seed contains AngularJS libraries, test libraries and a bunch of scripts all preconfigured for\ninstant web development gratification. Just clone the repo (or download the zip/tarball), start up\nour (or yours) webserver and you are ready to develop and test your application.\n\nThe seed app doesn't do much, just shows how to wire two controllers and views together. You can\ncheck it out by opening app/index.html in your browser (might not work file `file://` scheme in\ncertain browsers, see note below).\n\n_Note: While angular is client-side-only technology and it's possible to create angular webapps that\ndon't require a backend server at all, we recommend hosting the project files using a local\nwebserver during development to avoid issues with security restrictions (sandbox) in browsers. The\nsandbox implementation varies between browsers, but quite often prevents things like cookies, xhr,\netc to function properly when an html page is opened via `file://` scheme instead of `http://`._\n\n\n## How to use angular-seed\n\nClone the angular-seed repository and start hacking...\n\n\n### Running the app during development\n\nYou can pick one of these options:\n\n* serve this repository with your webserver\n* install node.js and run `scripts/web-server.js`\n\nThen navigate your browser to `http://localhost:<port>/app/index.html` to see the app running in\nyour browser.\n\n\n### Running the app in production\n\nThis really depends on how complex is your app and the overall infrastructure of your system, but\nthe general rule is that all you need in production are all the files under the `app/` directory.\nEverything else should be omitted.\n\nAngular apps are really just a bunch of static html, css and js files that just need to be hosted\nsomewhere, where they can be accessed by browsers.\n\nIf your Angular app is talking to the backend server via xhr or other means, you need to figure\nout what is the best way to host the static files to comply with the same origin policy if\napplicable. Usually this is done by hosting the files by the backend server or through\nreverse-proxying the backend server(s) and a webserver(s).\n\n\n### Running unit tests\n\nWe recommend using [jasmine](http://pivotal.github.com/jasmine/) and\n[Testacular](http://vojtajina.github.com/testacular/) for your unit tests/specs, but you are free\nto use whatever works for you.\n\nRequires [node.js](http://nodejs.org/), Testacular (`sudo npm install -g testacular`) and a local\nor remote browser.\n\n* start `scripts/test.sh` (on windows: `scripts\\test.bat`)\n  * a browser will start and connect to the Testacular server (Chrome is default browser, others can be captured by loading the same url as the one in Chrome or by changing the `config/testacular.conf.js` file)\n* to run or re-run tests just change any of your source or test javascript files\n\n\n### End to end testing\n\nAngular ships with a baked-in end-to-end test runner that understands angular, your app and allows\nyou to write your tests with jasmine-like BDD syntax.\n\nRequires a webserver, node.js + `./scripts/web-server.js` or your backend server that hosts the angular static files.\n\nCheck out the\n[end-to-end runner's documentation](http://docs.angularjs.org/guide/dev_guide.e2e-testing) for more\ninfo.\n\n* create your end-to-end tests in `test/e2e/scenarios.js`\n* serve your project directory with your http/backend server or node.js + `scripts/web-server.js`\n* to run do one of:\n  * open `http://localhost:port/test/e2e/runner.html` in your browser\n  * run the tests from console with [Testacular](vojtajina.github.com/testacular) via\n    `scripts/e2e-test.sh` or `script/e2e-test.bat`\n\n\n### Receiving updates from upstream\n\nWhen we upgrade angular-seed's repo with newer angular or testing library code, you can just\nfetch the changes and merge them into your project with git.\n\n\n## Directory Layout\n\n    app/                --> all of the files to be used in production\n      css/              --> css files\n        app.css         --> default stylesheet\n      img/              --> image files\n      index.html        --> app layout file (the main html template file of the app)\n      index-async.html  --> just like index.html, but loads js files asynchronously\n      js/               --> javascript files\n        app.js          --> application\n        controllers.js  --> application controllers\n        directives.js   --> application directives\n        filters.js      --> custom angular filters\n        services.js     --> custom angular services\n      lib/              --> angular and 3rd party javascript libraries\n        angular/\n          angular.js        --> the latest angular js\n          angular.min.js    --> the latest minified angular js\n          angular-*.js      --> angular add-on modules\n          version.txt       --> version number\n      partials/             --> angular view partials (partial html templates)\n        partial1.html\n        partial2.html\n\n    config/testacular.conf.js        --> config file for running unit tests with Testacular\n    config/testacular-e2e.conf.js    --> config file for running e2e tests with Testacular\n\n    scripts/            --> handy shell/js/ruby scripts\n      e2e-test.sh       --> runs end-to-end tests with Testacular (*nix)\n      e2e-test.bat      --> runs end-to-end tests with Testacular (windows)\n      test.bat          --> autotests unit tests with Testacular (windows)\n      test.sh           --> autotests unit tests with Testacular (*nix)\n      web-server.js     --> simple development webserver based on node.js\n\n    test/               --> test source files and libraries\n      e2e/              -->\n        runner.html     --> end-to-end test runner (open in your browser to run)\n        scenarios.js    --> end-to-end specs\n      lib/\n        angular/                --> angular testing libraries\n          angular-mocks.js      --> mocks that replace certain angular services in tests\n          angular-scenario.js   --> angular's scenario (end-to-end) test runner library\n          version.txt           --> version file\n      unit/                     --> unit level specs/tests\n        controllersSpec.js      --> specs for controllers\n        directivessSpec.js      --> specs for directives\n        filtersSpec.js          --> specs for filters\n        servicesSpec.js         --> specs for services\n\n## Contact\n\nFor more information on AngularJS please check out http://angularjs.org/\n"
  },
  {
    "path": "chapter2/recipe7/app/css/.gitignore",
    "content": ""
  },
  {
    "path": "chapter2/recipe7/app/css/app.css",
    "content": "/* app css stylesheet */\n\n.menu {\n  list-style: none;\n  border-bottom: 0.1em solid black;\n  margin-bottom: 2em;\n  padding: 0 0 0.5em;\n}\n\n.menu:before {\n  content: \"[\";\n}\n\n.menu:after {\n  content: \"]\";\n}\n\n.menu > li {\n  display: inline;\n}\n\n.menu > li:before {\n  content: \"|\";\n  padding-right: 0.3em;\n}\n\n.menu > li:nth-child(1):before {\n  content: \"\";\n  padding: 0;\n}\n"
  },
  {
    "path": "chapter2/recipe7/app/img/.gitignore",
    "content": ""
  },
  {
    "path": "chapter2/recipe7/app/index-async.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <style>\n    [ng-cloak] {\n      display: none;\n    }\n  </style>\n  <script>\n    // include angular loader, which allows the files to load in any order\n    /*\n     AngularJS v1.0.0rc1\n     (c) 2010-2012 AngularJS http://angularjs.org\n     License: MIT\n    */\n    'use strict';(function(i){function d(c,a,e){return c[a]||(c[a]=e())}return d(d(i,\"angular\",Object),\"module\",function(){var c={};return function(a,e,f){e&&c.hasOwnProperty(a)&&(c[a]=null);return d(c,a,function(){function b(a,b,d){return function(){c[d||\"push\"]([a,b,arguments]);return g}}if(!e)throw Error(\"No module: \"+a);var c=[],d=[],h=b(\"$injector\",\"invoke\"),g={_invokeQueue:c,_runBlocks:d,requires:e,name:a,provider:b(\"$provide\",\"provider\"),factory:b(\"$provide\",\"factory\"),service:b(\"$provide\",\"service\"),\n    value:b(\"$provide\",\"value\"),constant:b(\"$provide\",\"constant\",\"unshift\"),filter:b(\"$filterProvider\",\"register\"),directive:b(\"$compileProvider\",\"directive\"),config:h,run:function(a){d.push(a);return this}};f&&h(f);return g})}})})(window);\n\n    // include a third-party async loader library\n    /*!\n     * $script.js v1.3\n     * https://github.com/ded/script.js\n     * Copyright: @ded & @fat - Dustin Diaz, Jacob Thornton 2011\n     * Follow our software http://twitter.com/dedfat\n     * License: MIT\n     */\n    !function(a,b,c){function t(a,c){var e=b.createElement(\"script\"),f=j;e.onload=e.onerror=e[o]=function(){e[m]&&!/^c|loade/.test(e[m])||f||(e.onload=e[o]=null,f=1,c())},e.async=1,e.src=a,d.insertBefore(e,d.firstChild)}function q(a,b){p(a,function(a){return!b(a)})}var d=b.getElementsByTagName(\"head\")[0],e={},f={},g={},h={},i=\"string\",j=!1,k=\"push\",l=\"DOMContentLoaded\",m=\"readyState\",n=\"addEventListener\",o=\"onreadystatechange\",p=function(a,b){for(var c=0,d=a.length;c<d;++c)if(!b(a[c]))return j;return 1};!b[m]&&b[n]&&(b[n](l,function r(){b.removeEventListener(l,r,j),b[m]=\"complete\"},j),b[m]=\"loading\");var s=function(a,b,d){function o(){if(!--m){e[l]=1,j&&j();for(var a in g)p(a.split(\"|\"),n)&&!q(g[a],n)&&(g[a]=[])}}function n(a){return a.call?a():e[a]}a=a[k]?a:[a];var i=b&&b.call,j=i?b:d,l=i?a.join(\"\"):b,m=a.length;c(function(){q(a,function(a){h[a]?(l&&(f[l]=1),o()):(h[a]=1,l&&(f[l]=1),t(s.path?s.path+a+\".js\":a,o))})},0);return s};s.get=t,s.ready=function(a,b,c){a=a[k]?a:[a];var d=[];!q(a,function(a){e[a]||d[k](a)})&&p(a,function(a){return e[a]})?b():!function(a){g[a]=g[a]||[],g[a][k](b),c&&c(d)}(a.join(\"|\"));return s};var u=a.$script;s.noConflict=function(){a.$script=u;return this},typeof module!=\"undefined\"&&module.exports?module.exports=s:a.$script=s}(this,document,setTimeout)\n\n    // load all of the dependencies asynchronously.\n    $script([\n      'lib/angular/angular.js',\n      'js/app.js',\n      'js/services.js',\n      'js/controllers.js',\n      'js/filters.js',\n      'js/directives.js'\n    ], function() {\n      // when all is done, execute bootstrap angular application\n      angular.bootstrap(document, ['myApp']);\n    });\n  </script>\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\">\n</head>\n<body ng-cloak>\n  <ul class=\"menu\">\n    <li><a href=\"#/view1\">view1</a></li>\n    <li><a href=\"#/view2\">view2</a></li>\n  </ul>\n\n  <div ng-view></div>\n\n  <div>Angular seed app: v<span app-version></span></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "chapter2/recipe7/app/index.html",
    "content": "<!doctype html>\n<html lang=\"en\" ng-app>\n<head>\n  <meta charset=\"utf-8\">\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\"/>\n</head>\n<body>\n  <div ng-controller=\"MyCtrl\">\n    <input type=\"text\" ng-model=\"name\" placeholder=\"Enter your name\">\n    <p>{{greeting}}</p>\n  </div>\n\n  <script src=\"lib/angular/angular.js\"></script>\n  <script src=\"js/controllers.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "chapter2/recipe7/app/js/controllers.js",
    "content": "'use strict';\n\nfunction MyCtrl($scope) {\n  $scope.name = \"\";\n\n  $scope.$watch(\"name\", function() {\n    if ($scope.name.length > 0) {\n      $scope.greeting = \"Greetings \" + $scope.name;\n    }\n  });\n}\n\n"
  },
  {
    "path": "chapter2/recipe7/app/lib/angular/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngCookies\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookies\n   * @requires $browser\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from\n   * this object, new cookies are created/deleted at the end of current $eval.\n   *\n   * @example\n   */\n   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for(name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            if (angular.isDefined(lastCookies[name])) {\n              cookies[name] = lastCookies[name];\n            } else {\n              delete cookies[name];\n            }\n          } else if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated){\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   * @example\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#get\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          return angular.fromJson($cookies[key]);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#put\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#remove\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter2/recipe7/app/lib/angular/angular-loader.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n\n(\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n'use strict';\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n)(window);\n\n/**\n * Closure compiler type information\n *\n * @typedef { {\n *   requires: !Array.<string>,\n *   invokeQueue: !Array.<Array.<*>>,\n *\n *   service: function(string, Function):angular.Module,\n *   factory: function(string, Function):angular.Module,\n *   value: function(string, *):angular.Module,\n *\n *   filter: function(string, Function):angular.Module,\n *\n *   init: function(Function):angular.Module\n * } }\n */\nangular.Module;\n\n"
  },
  {
    "path": "chapter2/recipe7/app/lib/angular/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g. \n *   `http://example.com:8080/api`), you'll need to escape the colon character before the port\n *   number, like this: `$resource('http://example.com\\\\:8080/api')`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` – {string} – The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` – {object=} – Optional set of pre-bound parameters for this action.\n *   - isArray – {boolean=} – If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n     * encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace((pctEncodeSpaces ? null : /%20/g), '+');\n    }\n\n    function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        action.method = angular.uppercase(action.method);\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter2/recipe7/app/lib/angular/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             '<p style=\"color:blue\">an html\\n' +\n             '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n             'snippet</p>';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n          Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n           <table>\n             <tr>\n               <td>Filter</td>\n               <td>Source</td>\n               <td>Rendered</td>\n             </tr>\n             <tr id=\"html-filter\">\n               <td>html filter</td>\n               <td>\n                 <pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre>\n               </td>\n               <td>\n                 <div ng-bind-html=\"snippet\"></div>\n               </td>\n             </tr>\n             <tr id=\"escaped-html\">\n               <td>no filter</td>\n               <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind=\"snippet\"></div></td>\n             </tr>\n             <tr id=\"html-unsafe-filter\">\n               <td>unsafe html filter</td>\n               <td><pre>&lt;div ng-bind-html-unsafe=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind-html-unsafe=\"snippet\"></div></td>\n             </tr>\n           </table>\n         </div>\n     </doc:source>\n     <doc:scenario>\n       it('should sanitize the html snippet ', function() {\n         expect(using('#html-filter').element('div').html()).\n           toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n       });\n\n       it('should escape snippet without any filter', function() {\n         expect(using('#escaped-html').element('div').html()).\n           toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n                \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n                \"snippet&lt;/p&gt;\");\n       });\n\n       it('should inline raw snippet if filtered as unsafe', function() {\n         expect(using('#html-unsafe-filter').element(\"div\").html()).\n           toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n                \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n                \"snippet</p>\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new <b>text</b>');\n         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');\n         expect(using('#escaped-html').element('div').html()).toBe(\"new &lt;b&gt;text&lt;/b&gt;\");\n         expect(using('#html-unsafe-filter').binding(\"snippet\")).toBe('new <b>text</b>');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar $sanitize = function(html) {\n  var buf = [];\n    htmlParser(html, htmlSanitizeWriter(buf));\n    return buf.join('');\n};\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP = /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  URI_REGEXP = /^((ftp|https?):\\/\\/|mailto:|#)/,\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g; // Match everything outside of normal chars and \" (quote character)\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,aside,\" +\n        \"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,\" +\n        \"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,bdi,bdo,\" +\n        \"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,\" +\n        \"span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        index = html.indexOf(\"-->\");\n\n        if ( index >= 0 ) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'), function(all, text){\n        text = text.\n          replace(COMMENT_REGEXP, \"$1\").\n          replace(CDATA_REGEXP, \"$1\");\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n\n        return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw \"Parse Error: \" + html;\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {\n      var value = doubleQuotedValue\n        || singleQoutedValue\n        || unqoutedValue\n        || '';\n\n      attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nvar hiddenPre=document.createElement(\"pre\");\nfunction decodeEntities(value) {\n  hiddenPre.innerHTML=value.replace(/</g,\"&lt;\");\n  return hiddenPre.innerText || hiddenPre.textContent || '';\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] == true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] == true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).value('$sanitize', $sanitize);\n\n/**\n * @ngdoc directive\n * @name ngSanitize.directive:ngBindHtml\n *\n * @description\n * Creates a binding that will sanitize the result of evaluating the `expression` with the\n * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n */\nangular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);\n    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {\n      value = $sanitize(value);\n      element.html(value || '');\n    });\n  };\n}]);\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n *   plain email address links.\n *\n * @param {string} text Input text.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should linkify the snippet with urls', function() {\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('Pretty text with some links:&#10;' +\n                '<a href=\"http://angularjs.org/\">http://angularjs.org/</a>,&#10;' +\n                '<a href=\"mailto:us@somewhere.org\">us@somewhere.org</a>,&#10;' +\n                '<a href=\"mailto:another@somewhere.org\">another@somewhere.org</a>,&#10;' +\n                'and one more: <a href=\"ftp://127.0.0.1/\">ftp://127.0.0.1/</a>.');\n       });\n\n       it ('should not linkify snippet without the linky filter', function() {\n         expect(using('#escaped-html').binding('snippet')).\n           toBe(\"Pretty text with some links:\\n\" +\n                \"http://angularjs.org/,\\n\" +\n                \"mailto:us@somewhere.org,\\n\" +\n                \"another@somewhere.org,\\n\" +\n                \"and one more: ftp://127.0.0.1/.\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new http://link.');\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('new <a href=\"http://link\">http://link</a>.');\n         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', function() {\n  var LINKY_URL_REGEXP = /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s\\.\\;\\,\\(\\)\\{\\}\\<\\>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    // TODO(vojta): use $sanitize instead\n    var writer = htmlSanitizeWriter(html);\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      writer.chars(raw.substr(0, i));\n      writer.start('a', {href:url});\n      writer.chars(match[0].replace(MAILTO_REGEXP, ''));\n      writer.end('a');\n      raw = raw.substring(i + match[0].length);\n    }\n    writer.chars(raw);\n    return html.join('');\n  };\n});\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter2/recipe7/app/lib/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter2/recipe7/app/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter2/recipe7/app/partials/.gitignore",
    "content": ""
  },
  {
    "path": "chapter2/recipe7/app/partials/partial1.html",
    "content": "<p>This is the partial for view 1.</p>\n"
  },
  {
    "path": "chapter2/recipe7/app/partials/partial2.html",
    "content": "<p>This is the partial for view 2.</p>\n<p>\n  Showing of 'interpolate' filter:\n  {{ 'Current version is v%VERSION%.' | interpolate }}\n</p>\n"
  },
  {
    "path": "chapter2/recipe7/config/testacular-e2e.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  ANGULAR_SCENARIO,\n  ANGULAR_SCENARIO_ADAPTER,\n  'test/e2e/**/*.js'\n];\n\nautoWatch = false;\n\nbrowsers = ['Chrome'];\n\nsingleRun = true;\n\nproxies = {\n  '/': 'http://localhost:8000/'\n};\n\njunitReporter = {\n  outputFile: 'test_out/e2e.xml',\n  suite: 'e2e'\n};\n"
  },
  {
    "path": "chapter2/recipe7/config/testacular.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  JASMINE,\n  JASMINE_ADAPTER,\n  'app/lib/angular/angular.js',\n  'app/lib/angular/angular-*.js',\n  'test/lib/angular/angular-mocks.js',\n  'app/js/**/*.js',\n  'test/unit/**/*.js'\n];\n\nautoWatch = true;\n\nbrowsers = ['Chrome'];\n\njunitReporter = {\n  outputFile: 'test_out/unit.xml',\n  suite: 'unit'\n};\n"
  },
  {
    "path": "chapter2/recipe7/logs/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "chapter2/recipe7/scripts/e2e-test.bat",
    "content": "@echo off\n\nREM Windows script for running e2e tests\nREM You have to run server and capture some browser first\nREM\nREM Requirements:\nREM - NodeJS (http://nodejs.org/)\nREM - Testacular (npm install -g testacular)\n\nset BASE_DIR=%~dp0\ntestacular start \"%BASE_DIR%\\..\\config\\testacular-e2e.conf.js\" %*\n"
  },
  {
    "path": "chapter2/recipe7/scripts/e2e-test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular-e2e.conf.js $*\n"
  },
  {
    "path": "chapter2/recipe7/scripts/test.bat",
    "content": "@echo off\r\n\r\nREM Windows script for running unit tests\r\nREM You have to run server and capture some browser first\r\nREM\r\nREM Requirements:\r\nREM - NodeJS (http://nodejs.org/)\r\nREM - Testacular (npm install -g testacular)\r\n\r\nset BASE_DIR=%~dp0\r\ntestacular start \"%BASE_DIR%\\..\\config\\testacular.conf.js\" %*\r\n"
  },
  {
    "path": "chapter2/recipe7/scripts/test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular.conf.js $*\n"
  },
  {
    "path": "chapter2/recipe7/scripts/watchr.rb",
    "content": "#!/usr/bin/env watchr\n\n# config file for watchr http://github.com/mynyml/watchr\n# install: gem install watchr\n# run: watch watchr.rb\n# note: make sure that you have jstd server running (server.sh) and a browser captured\n\nlog_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log')\n\n`cd ..`\n`touch #{log_file}`\n\nputs \"String watchr... log file: #{log_file}\"\n\nwatch( '(app/js|test/unit)' )  do\n  `echo \"\\n\\ntest run started @ \\`date\\`\" > #{log_file}`\n  `scripts/test.sh &> #{log_file}`\nend\n\n"
  },
  {
    "path": "chapter2/recipe7/scripts/web-server.js",
    "content": "#!/usr/bin/env node\n\nvar util = require('util'),\n    http = require('http'),\n    fs = require('fs'),\n    url = require('url'),\n    events = require('events');\n\nvar DEFAULT_PORT = 8000;\n\nfunction main(argv) {\n  new HttpServer({\n    'GET': createServlet(StaticServlet),\n    'HEAD': createServlet(StaticServlet)\n  }).start(Number(argv[2]) || DEFAULT_PORT);\n}\n\nfunction escapeHtml(value) {\n  return value.toString().\n    replace('<', '&lt;').\n    replace('>', '&gt;').\n    replace('\"', '&quot;');\n}\n\nfunction createServlet(Class) {\n  var servlet = new Class();\n  return servlet.handleRequest.bind(servlet);\n}\n\n/**\n * An Http server implementation that uses a map of methods to decide\n * action routing.\n *\n * @param {Object} Map of method => Handler function\n */\nfunction HttpServer(handlers) {\n  this.handlers = handlers;\n  this.server = http.createServer(this.handleRequest_.bind(this));\n}\n\nHttpServer.prototype.start = function(port) {\n  this.port = port;\n  this.server.listen(port);\n  util.puts('Http Server running at http://localhost:' + port + '/');\n};\n\nHttpServer.prototype.parseUrl_ = function(urlString) {\n  var parsed = url.parse(urlString);\n  parsed.pathname = url.resolve('/', parsed.pathname);\n  return url.parse(url.format(parsed), true);\n};\n\nHttpServer.prototype.handleRequest_ = function(req, res) {\n  var logEntry = req.method + ' ' + req.url;\n  if (req.headers['user-agent']) {\n    logEntry += ' ' + req.headers['user-agent'];\n  }\n  util.puts(logEntry);\n  req.url = this.parseUrl_(req.url);\n  var handler = this.handlers[req.method];\n  if (!handler) {\n    res.writeHead(501);\n    res.end();\n  } else {\n    handler.call(this, req, res);\n  }\n};\n\n/**\n * Handles static content.\n */\nfunction StaticServlet() {}\n\nStaticServlet.MimeMap = {\n  'txt': 'text/plain',\n  'html': 'text/html',\n  'css': 'text/css',\n  'xml': 'application/xml',\n  'json': 'application/json',\n  'js': 'application/javascript',\n  'jpg': 'image/jpeg',\n  'jpeg': 'image/jpeg',\n  'gif': 'image/gif',\n  'png': 'image/png',\n  'svg': 'image/svg+xml'\n};\n\nStaticServlet.prototype.handleRequest = function(req, res) {\n  var self = this;\n  var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){\n    return String.fromCharCode(parseInt(hex, 16));\n  });\n  var parts = path.split('/');\n  if (parts[parts.length-1].charAt(0) === '.')\n    return self.sendForbidden_(req, res, path);\n  fs.stat(path, function(err, stat) {\n    if (err)\n      return self.sendMissing_(req, res, path);\n    if (stat.isDirectory())\n      return self.sendDirectory_(req, res, path);\n    return self.sendFile_(req, res, path);\n  });\n}\n\nStaticServlet.prototype.sendError_ = function(req, res, error) {\n  res.writeHead(500, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>Internal Server Error</title>\\n');\n  res.write('<h1>Internal Server Error</h1>');\n  res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');\n  util.puts('500 Internal Server Error');\n  util.puts(util.inspect(error));\n};\n\nStaticServlet.prototype.sendMissing_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(404, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>404 Not Found</title>\\n');\n  res.write('<h1>Not Found</h1>');\n  res.write(\n    '<p>The requested URL ' +\n    escapeHtml(path) +\n    ' was not found on this server.</p>'\n  );\n  res.end();\n  util.puts('404 Not Found: ' + path);\n};\n\nStaticServlet.prototype.sendForbidden_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(403, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>403 Forbidden</title>\\n');\n  res.write('<h1>Forbidden</h1>');\n  res.write(\n    '<p>You do not have permission to access ' +\n    escapeHtml(path) + ' on this server.</p>'\n  );\n  res.end();\n  util.puts('403 Forbidden: ' + path);\n};\n\nStaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {\n  res.writeHead(301, {\n      'Content-Type': 'text/html',\n      'Location': redirectUrl\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>301 Moved Permanently</title>\\n');\n  res.write('<h1>Moved Permanently</h1>');\n  res.write(\n    '<p>The document has moved <a href=\"' +\n    redirectUrl +\n    '\">here</a>.</p>'\n  );\n  res.end();\n  util.puts('301 Moved Permanently: ' + redirectUrl);\n};\n\nStaticServlet.prototype.sendFile_ = function(req, res, path) {\n  var self = this;\n  var file = fs.createReadStream(path);\n  res.writeHead(200, {\n    'Content-Type': StaticServlet.\n      MimeMap[path.split('.').pop()] || 'text/plain'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n  } else {\n    file.on('data', res.write.bind(res));\n    file.on('close', function() {\n      res.end();\n    });\n    file.on('error', function(error) {\n      self.sendError_(req, res, error);\n    });\n  }\n};\n\nStaticServlet.prototype.sendDirectory_ = function(req, res, path) {\n  var self = this;\n  if (path.match(/[^\\/]$/)) {\n    req.url.pathname += '/';\n    var redirectUrl = url.format(url.parse(url.format(req.url)));\n    return self.sendRedirect_(req, res, redirectUrl);\n  }\n  fs.readdir(path, function(err, files) {\n    if (err)\n      return self.sendError_(req, res, error);\n\n    if (!files.length)\n      return self.writeDirectoryIndex_(req, res, path, []);\n\n    var remaining = files.length;\n    files.forEach(function(fileName, index) {\n      fs.stat(path + '/' + fileName, function(err, stat) {\n        if (err)\n          return self.sendError_(req, res, err);\n        if (stat.isDirectory()) {\n          files[index] = fileName + '/';\n        }\n        if (!(--remaining))\n          return self.writeDirectoryIndex_(req, res, path, files);\n      });\n    });\n  });\n};\n\nStaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {\n  path = path.substring(1);\n  res.writeHead(200, {\n    'Content-Type': 'text/html'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n    return;\n  }\n  res.write('<!doctype html>\\n');\n  res.write('<title>' + escapeHtml(path) + '</title>\\n');\n  res.write('<style>\\n');\n  res.write('  ol { list-style-type: none; font-size: 1.2em; }\\n');\n  res.write('</style>\\n');\n  res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');\n  res.write('<ol>');\n  files.forEach(function(fileName) {\n    if (fileName.charAt(0) !== '.') {\n      res.write('<li><a href=\"' +\n        escapeHtml(fileName) + '\">' +\n        escapeHtml(fileName) + '</a></li>');\n    }\n  });\n  res.write('</ol>');\n  res.end();\n};\n\n// Must be last,\nmain(process.argv);\n"
  },
  {
    "path": "chapter2/recipe7/test/e2e/runner.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <title>End2end Test Runner</title>\n    <script src=\"../lib/angular/angular-scenario.js\" ng-autotest></script>\n    <script src=\"scenarios.js\"></script>\n  </head>\n  <body>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter2/recipe7/test/e2e/scenarios.js",
    "content": "'use strict';\n\n/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */\n\ndescribe('my app', function() {\n\n  beforeEach(function() {\n    browser().navigateTo('../../app/index.html');\n  });\n\n\n  it('should automatically redirect to /view1 when location hash/fragment is empty', function() {\n    expect(browser().location().url()).toBe(\"/view1\");\n  });\n\n\n  describe('view1', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view1');\n    });\n\n\n    it('should render view1 when user navigates to /view1', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 1/);\n    });\n\n  });\n\n\n  describe('view2', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view2');\n    });\n\n\n    it('should render view2 when user navigates to /view2', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 2/);\n    });\n\n  });\n});\n"
  },
  {
    "path": "chapter2/recipe7/test/lib/angular/angular-mocks.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n *\n * TODO(vojta): wrap whole file into closure during build\n */\n\n/**\n * @ngdoc overview\n * @name angular.mock\n * @description\n *\n * Namespace from 'angular-mocks.js' which contains testing related code.\n */\nangular.mock = {};\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ngMock.$browser\n *\n * @description\n * This service is a mock implementation of {@link ng.$browser}. It provides fake\n * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,\n * cookies, etc...\n *\n * The api of this service is the same as that of the real {@link ng.$browser $browser}, except\n * that there are several helper methods available which can be used in tests.\n */\nangular.mock.$BrowserProvider = function() {\n  this.$get = function(){\n    return new angular.mock.$Browser();\n  };\n};\n\nangular.mock.$Browser = function() {\n  var self = this;\n\n  this.isMock = true;\n  self.$$url = \"http://server/\";\n  self.$$lastUrl = self.$$url; // used by url polling fn\n  self.pollFns = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = angular.noop;\n  self.$$incOutstandingRequestCount = angular.noop;\n\n\n  // register url polling fn\n\n  self.onUrlChange = function(listener) {\n    self.pollFns.push(\n      function() {\n        if (self.$$lastUrl != self.$$url) {\n          self.$$lastUrl = self.$$url;\n          listener(self.$$url);\n        }\n      }\n    );\n\n    return listener;\n  };\n\n  self.cookieHash = {};\n  self.lastCookieHash = {};\n  self.deferredFns = [];\n  self.deferredNextId = 0;\n\n  self.defer = function(fn, delay) {\n    delay = delay || 0;\n    self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});\n    self.deferredFns.sort(function(a,b){ return a.time - b.time;});\n    return self.deferredNextId++;\n  };\n\n\n  self.defer.now = 0;\n\n\n  self.defer.cancel = function(deferId) {\n    var fnIndex;\n\n    angular.forEach(self.deferredFns, function(fn, index) {\n      if (fn.id === deferId) fnIndex = index;\n    });\n\n    if (fnIndex !== undefined) {\n      self.deferredFns.splice(fnIndex, 1);\n      return true;\n    }\n\n    return false;\n  };\n\n\n  /**\n   * @name ngMock.$browser#defer.flush\n   * @methodOf ngMock.$browser\n   *\n   * @description\n   * Flushes all pending requests and executes the defer callbacks.\n   *\n   * @param {number=} number of milliseconds to flush. See {@link #defer.now}\n   */\n  self.defer.flush = function(delay) {\n    if (angular.isDefined(delay)) {\n      self.defer.now += delay;\n    } else {\n      if (self.deferredFns.length) {\n        self.defer.now = self.deferredFns[self.deferredFns.length-1].time;\n      } else {\n        throw Error('No deferred tasks to be flushed');\n      }\n    }\n\n    while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {\n      self.deferredFns.shift().fn();\n    }\n  };\n  /**\n   * @name ngMock.$browser#defer.now\n   * @propertyOf ngMock.$browser\n   *\n   * @description\n   * Current milliseconds mock time.\n   */\n\n  self.$$baseHref = '';\n  self.baseHref = function() {\n    return this.$$baseHref;\n  };\n};\nangular.mock.$Browser.prototype = {\n\n/**\n  * @name ngMock.$browser#poll\n  * @methodOf ngMock.$browser\n  *\n  * @description\n  * run all fns in pollFns\n  */\n  poll: function poll() {\n    angular.forEach(this.pollFns, function(pollFn){\n      pollFn();\n    });\n  },\n\n  addPollFn: function(pollFn) {\n    this.pollFns.push(pollFn);\n    return pollFn;\n  },\n\n  url: function(url, replace) {\n    if (url) {\n      this.$$url = url;\n      return this;\n    }\n\n    return this.$$url;\n  },\n\n  cookies:  function(name, value) {\n    if (name) {\n      if (value == undefined) {\n        delete this.cookieHash[name];\n      } else {\n        if (angular.isString(value) &&       //strings only\n            value.length <= 4096) {          //strict cookie storage limits\n          this.cookieHash[name] = value;\n        }\n      }\n    } else {\n      if (!angular.equals(this.cookieHash, this.lastCookieHash)) {\n        this.lastCookieHash = angular.copy(this.cookieHash);\n        this.cookieHash = angular.copy(this.cookieHash);\n      }\n      return this.cookieHash;\n    }\n  },\n\n  notifyWhenNoOutstandingRequests: function(fn) {\n    fn();\n  }\n};\n\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandlerProvider\n *\n * @description\n * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed\n * into the `$exceptionHandler`.\n */\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandler\n *\n * @description\n * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed\n * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration\n * information.\n *\n *\n * <pre>\n *   describe('$exceptionHandlerProvider', function() {\n *\n *     it('should capture log messages and exceptions', function() {\n *\n *       module(function($exceptionHandlerProvider) {\n *         $exceptionHandlerProvider.mode('log');\n *       });\n *\n *       inject(function($log, $exceptionHandler, $timeout) {\n *         $timeout(function() { $log.log(1); });\n *         $timeout(function() { $log.log(2); throw 'banana peel'; });\n *         $timeout(function() { $log.log(3); });\n *         expect($exceptionHandler.errors).toEqual([]);\n *         expect($log.assertEmpty());\n *         $timeout.flush();\n *         expect($exceptionHandler.errors).toEqual(['banana peel']);\n *         expect($log.log.logs).toEqual([[1], [2], [3]]);\n *       });\n *     });\n *   });\n * </pre>\n */\n\nangular.mock.$ExceptionHandlerProvider = function() {\n  var handler;\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$exceptionHandlerProvider#mode\n   * @methodOf ngMock.$exceptionHandlerProvider\n   *\n   * @description\n   * Sets the logging mode.\n   *\n   * @param {string} mode Mode of operation, defaults to `rethrow`.\n   *\n   *   - `rethrow`: If any errors are are passed into the handler in tests, it typically\n   *                means that there is a bug in the application or test, so this mock will\n   *                make these tests fail.\n   *   - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores an\n   *            array of errors in `$exceptionHandler.errors`, to allow later assertion of them.\n   *            See {@link ngMock.$log#assertEmpty assertEmpty()} and\n   *             {@link ngMock.$log#reset reset()}\n   */\n  this.mode = function(mode) {\n    switch(mode) {\n      case 'rethrow':\n        handler = function(e) {\n          throw e;\n        };\n        break;\n      case 'log':\n        var errors = [];\n\n        handler = function(e) {\n          if (arguments.length == 1) {\n            errors.push(e);\n          } else {\n            errors.push([].slice.call(arguments, 0));\n          }\n        };\n\n        handler.errors = errors;\n        break;\n      default:\n        throw Error(\"Unknown mode '\" + mode + \"', only 'log'/'rethrow' modes are allowed!\");\n    }\n  };\n\n  this.$get = function() {\n    return handler;\n  };\n\n  this.mode('rethrow');\n};\n\n\n/**\n * @ngdoc service\n * @name ngMock.$log\n *\n * @description\n * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays\n * (one array per logging level). These arrays are exposed as `logs` property of each of the\n * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.\n *\n */\nangular.mock.$LogProvider = function() {\n\n  function concat(array1, array2, index) {\n    return array1.concat(Array.prototype.slice.call(array2, index));\n  }\n\n\n  this.$get = function () {\n    var $log = {\n      log: function() { $log.log.logs.push(concat([], arguments, 0)); },\n      warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },\n      info: function() { $log.info.logs.push(concat([], arguments, 0)); },\n      error: function() { $log.error.logs.push(concat([], arguments, 0)); }\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#reset\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Reset all of the logging arrays to empty.\n     */\n    $log.reset = function () {\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#log.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.log.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#warn.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.warn.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#info.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.info.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#error.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.error.logs = [];\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#assertEmpty\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.\n     */\n    $log.assertEmpty = function() {\n      var errors = [];\n      angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {\n        angular.forEach($log[logLevel].logs, function(log) {\n          angular.forEach(log, function (logItem) {\n            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\\n' + (logItem.stack || ''));\n          });\n        });\n      });\n      if (errors.length) {\n        errors.unshift(\"Expected $log to be empty! Either a message was logged unexpectedly, or an expected \" +\n          \"log message was not checked and removed:\");\n        errors.push('');\n        throw new Error(errors.join('\\n---------\\n'));\n      }\n    };\n\n    $log.reset();\n    return $log;\n  };\n};\n\n\n(function() {\n  var R_ISO8061_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?:\\:?(\\d\\d)(?:\\:?(\\d\\d)(?:\\.(\\d{3}))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d)))?$/;\n\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8061_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n  function int(str) {\n    return parseInt(str, 10);\n  }\n\n  function padNumber(num, digits, trim) {\n    var neg = '';\n    if (num < 0) {\n      neg =  '-';\n      num = -num;\n    }\n    num = '' + num;\n    while(num.length < digits) num = '0' + num;\n    if (trim)\n      num = num.substr(num.length - digits);\n    return neg + num;\n  }\n\n\n  /**\n   * @ngdoc object\n   * @name angular.mock.TzDate\n   * @description\n   *\n   * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.\n   *\n   * Mock of the Date type which has its timezone specified via constroctor arg.\n   *\n   * The main purpose is to create Date-like instances with timezone fixed to the specified timezone\n   * offset, so that we can test code that depends on local timezone settings without dependency on\n   * the time zone settings of the machine where the code is running.\n   *\n   * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)\n   * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*\n   *\n   * @example\n   * !!!! WARNING !!!!!\n   * This is not a complete Date object so only methods that were implemented can be called safely.\n   * To make matters worse, TzDate instances inherit stuff from Date via a prototype.\n   *\n   * We do our best to intercept calls to \"unimplemented\" methods, but since the list of methods is\n   * incomplete we might be missing some non-standard methods. This can result in errors like:\n   * \"Date.prototype.foo called on incompatible Object\".\n   *\n   * <pre>\n   * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');\n   * newYearInBratislava.getTimezoneOffset() => -60;\n   * newYearInBratislava.getFullYear() => 2010;\n   * newYearInBratislava.getMonth() => 0;\n   * newYearInBratislava.getDate() => 1;\n   * newYearInBratislava.getHours() => 0;\n   * newYearInBratislava.getMinutes() => 0;\n   * </pre>\n   *\n   */\n  angular.mock.TzDate = function (offset, timestamp) {\n    var self = new Date(0);\n    if (angular.isString(timestamp)) {\n      var tsStr = timestamp;\n\n      self.origDate = jsonStringToDate(timestamp);\n\n      timestamp = self.origDate.getTime();\n      if (isNaN(timestamp))\n        throw {\n          name: \"Illegal Argument\",\n          message: \"Arg '\" + tsStr + \"' passed into TzDate constructor is not a valid date string\"\n        };\n    } else {\n      self.origDate = new Date(timestamp);\n    }\n\n    var localOffset = new Date(timestamp).getTimezoneOffset();\n    self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;\n    self.date = new Date(timestamp + self.offsetDiff);\n\n    self.getTime = function() {\n      return self.date.getTime() - self.offsetDiff;\n    };\n\n    self.toLocaleDateString = function() {\n      return self.date.toLocaleDateString();\n    };\n\n    self.getFullYear = function() {\n      return self.date.getFullYear();\n    };\n\n    self.getMonth = function() {\n      return self.date.getMonth();\n    };\n\n    self.getDate = function() {\n      return self.date.getDate();\n    };\n\n    self.getHours = function() {\n      return self.date.getHours();\n    };\n\n    self.getMinutes = function() {\n      return self.date.getMinutes();\n    };\n\n    self.getSeconds = function() {\n      return self.date.getSeconds();\n    };\n\n    self.getTimezoneOffset = function() {\n      return offset * 60;\n    };\n\n    self.getUTCFullYear = function() {\n      return self.origDate.getUTCFullYear();\n    };\n\n    self.getUTCMonth = function() {\n      return self.origDate.getUTCMonth();\n    };\n\n    self.getUTCDate = function() {\n      return self.origDate.getUTCDate();\n    };\n\n    self.getUTCHours = function() {\n      return self.origDate.getUTCHours();\n    };\n\n    self.getUTCMinutes = function() {\n      return self.origDate.getUTCMinutes();\n    };\n\n    self.getUTCSeconds = function() {\n      return self.origDate.getUTCSeconds();\n    };\n\n    self.getUTCMilliseconds = function() {\n      return self.origDate.getUTCMilliseconds();\n    };\n\n    self.getDay = function() {\n      return self.date.getDay();\n    };\n\n    // provide this method only on browsers that already have it\n    if (self.toISOString) {\n      self.toISOString = function() {\n        return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +\n              padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +\n              padNumber(self.origDate.getUTCDate(), 2) + 'T' +\n              padNumber(self.origDate.getUTCHours(), 2) + ':' +\n              padNumber(self.origDate.getUTCMinutes(), 2) + ':' +\n              padNumber(self.origDate.getUTCSeconds(), 2) + '.' +\n              padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'\n      }\n    }\n\n    //hide all methods not implemented in this mock that the Date prototype exposes\n    var unimplementedMethods = ['getMilliseconds', 'getUTCDay',\n        'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',\n        'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',\n        'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',\n        'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',\n        'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];\n\n    angular.forEach(unimplementedMethods, function(methodName) {\n      self[methodName] = function() {\n        throw Error(\"Method '\" + methodName + \"' is not implemented in the TzDate mock\");\n      };\n    });\n\n    return self;\n  };\n\n  //make \"tzDateInstance instanceof Date\" return true\n  angular.mock.TzDate.prototype = Date.prototype;\n})();\n\n\n/**\n * @ngdoc function\n * @name angular.mock.dump\n * @description\n *\n * *NOTE*: this is not an injectable instance, just a globally available function.\n *\n * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.\n *\n * This method is also available on window, where it can be used to display objects on debug console.\n *\n * @param {*} object - any object to turn into string.\n * @return {string} a serialized string of the argument\n */\nangular.mock.dump = function(object) {\n  return serialize(object);\n\n  function serialize(object) {\n    var out;\n\n    if (angular.isElement(object)) {\n      object = angular.element(object);\n      out = angular.element('<div></div>');\n      angular.forEach(object, function(element) {\n        out.append(angular.element(element).clone());\n      });\n      out = out.html();\n    } else if (angular.isArray(object)) {\n      out = [];\n      angular.forEach(object, function(o) {\n        out.push(serialize(o));\n      });\n      out = '[ ' + out.join(', ') + ' ]';\n    } else if (angular.isObject(object)) {\n      if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {\n        out = serializeScope(object);\n      } else if (object instanceof Error) {\n        out = object.stack || ('' + object.name + ': ' + object.message);\n      } else {\n        out = angular.toJson(object, true);\n      }\n    } else {\n      out = String(object);\n    }\n\n    return out;\n  }\n\n  function serializeScope(scope, offset) {\n    offset = offset ||  '  ';\n    var log = [offset + 'Scope(' + scope.$id + '): {'];\n    for ( var key in scope ) {\n      if (scope.hasOwnProperty(key) && !key.match(/^(\\$|this)/)) {\n        log.push('  ' + key + ': ' + angular.toJson(scope[key]));\n      }\n    }\n    var child = scope.$$childHead;\n    while(child) {\n      log.push(serializeScope(child, offset + '  '));\n      child = child.$$nextSibling;\n    }\n    log.push('}');\n    return log.join('\\n' + offset);\n  }\n};\n\n/**\n * @ngdoc object\n * @name ngMock.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for unit testing application that use the\n * {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less\n * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.\n *\n * During unit testing, we want our unit tests to run quickly and have no external dependencies so\n * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or\n * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is\n * to verify whether a certain request has been sent or not, or alternatively just let the\n * application make requests, respond with pre-trained responses and assert that the end result is\n * what we expect it to be.\n *\n * This mock implementation can be used to respond with static or dynamic responses via the\n * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).\n *\n * When an Angular application needs some data from a server, it calls the $http service, which\n * sends the request to a real server using $httpBackend service. With dependency injection, it is\n * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify\n * the requests and respond with some testing data without sending a request to real server.\n *\n * There are two ways to specify what test data should be returned as http responses by the mock\n * backend when the code under test makes http requests:\n *\n * - `$httpBackend.expect` - specifies a request expectation\n * - `$httpBackend.when` - specifies a backend definition\n *\n *\n * # Request Expectations vs Backend Definitions\n *\n * Request expectations provide a way to make assertions about requests made by the application and\n * to define responses for those requests. The test will fail if the expected requests are not made\n * or they are made in the wrong order.\n *\n * Backend definitions allow you to define a fake backend for your application which doesn't assert\n * if a particular request was made or not, it just returns a trained response if a request is made.\n * The test will pass whether or not the request gets made during testing.\n *\n *\n * <table class=\"table\">\n *   <tr><th width=\"220px\"></th><th>Request expectations</th><th>Backend definitions</th></tr>\n *   <tr>\n *     <th>Syntax</th>\n *     <td>.expect(...).respond(...)</td>\n *     <td>.when(...).respond(...)</td>\n *   </tr>\n *   <tr>\n *     <th>Typical usage</th>\n *     <td>strict unit tests</td>\n *     <td>loose (black-box) unit testing</td>\n *   </tr>\n *   <tr>\n *     <th>Fulfills multiple requests</th>\n *     <td>NO</td>\n *     <td>YES</td>\n *   </tr>\n *   <tr>\n *     <th>Order of requests matters</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Request required</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Response required</th>\n *     <td>optional (see below)</td>\n *     <td>YES</td>\n *   </tr>\n * </table>\n *\n * In cases where both backend definitions and request expectations are specified during unit\n * testing, the request expectations are evaluated first.\n *\n * If a request expectation has no response specified, the algorithm will search your backend\n * definitions for an appropriate response.\n *\n * If a request didn't match any expectation or if the expectation doesn't have the response\n * defined, the backend definitions are evaluated in sequential order to see if any of them match\n * the request. The response from the first matched definition is returned.\n *\n *\n * # Flushing HTTP requests\n *\n * The $httpBackend used in production, always responds to requests with responses asynchronously.\n * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are\n * hard to write, follow and maintain. At the same time the testing mock, can't respond\n * synchronously because that would change the execution of the code under test. For this reason the\n * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending\n * requests and thus preserving the async api of the backend, while allowing the test to execute\n * synchronously.\n *\n *\n * # Unit testing with mock $httpBackend\n *\n * <pre>\n   // controller\n   function MyController($scope, $http) {\n     $http.get('/auth.py').success(function(data) {\n       $scope.user = data;\n     });\n\n     this.saveMessage = function(message) {\n       $scope.status = 'Saving...';\n       $http.post('/add-msg.py', message).success(function(response) {\n         $scope.status = '';\n       }).error(function() {\n         $scope.status = 'ERROR!';\n       });\n     };\n   }\n\n   // testing controller\n   var $httpBackend;\n\n   beforeEach(inject(function($injector) {\n     $httpBackend = $injector.get('$httpBackend');\n\n     // backend definition common for all tests\n     $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});\n   }));\n\n\n   afterEach(function() {\n     $httpBackend.verifyNoOutstandingExpectation();\n     $httpBackend.verifyNoOutstandingRequest();\n   });\n\n\n   it('should fetch authentication token', function() {\n     $httpBackend.expectGET('/auth.py');\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n   });\n\n\n   it('should send msg to server', function() {\n     // now you don’t care about the authentication, but\n     // the controller will still send the request and\n     // $httpBackend will respond without you having to\n     // specify the expectation and response for this request\n     $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');\n\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n     controller.saveMessage('message content');\n     expect(controller.status).toBe('Saving...');\n     $httpBackend.flush();\n     expect(controller.status).toBe('');\n   });\n\n\n   it('should send auth header', function() {\n     $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {\n       // check if the header was send, if it wasn't the expectation won't\n       // match the request and the test will fail\n       return headers['Authorization'] == 'xxx';\n     }).respond(201, '');\n\n     var controller = scope.$new(MyController);\n     controller.saveMessage('whatever');\n     $httpBackend.flush();\n   });\n   </pre>\n */\nangular.mock.$HttpBackendProvider = function() {\n  this.$get = [createHttpBackendMock];\n};\n\n/**\n * General factory function for $httpBackend mock.\n * Returns instance for unit testing (when no arguments specified):\n *   - passing through is disabled\n *   - auto flushing is disabled\n *\n * Returns instance for e2e testing (when `$delegate` and `$browser` specified):\n *   - passing through (delegating request to real backend) is enabled\n *   - auto flushing is enabled\n *\n * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)\n * @param {Object=} $browser Auto-flushing enabled if specified\n * @return {Object} Instance of $httpBackend mock\n */\nfunction createHttpBackendMock($delegate, $browser) {\n  var definitions = [],\n      expectations = [],\n      responses = [],\n      responsesPush = angular.bind(responses, responses.push);\n\n  function createResponse(status, data, headers) {\n    if (angular.isFunction(status)) return status;\n\n    return function() {\n      return angular.isNumber(status)\n          ? [status, data, headers]\n          : [200, status, data];\n    };\n  }\n\n  // TODO(vojta): change params to: method, url, data, headers, callback\n  function $httpBackend(method, url, data, callback, headers) {\n    var xhr = new MockXhr(),\n        expectation = expectations[0],\n        wasExpected = false;\n\n    function prettyPrint(data) {\n      return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)\n          ? data\n          : angular.toJson(data);\n    }\n\n    if (expectation && expectation.match(method, url)) {\n      if (!expectation.matchData(data))\n        throw Error('Expected ' + expectation + ' with different data\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.data) + '\\nGOT:      ' + data);\n\n      if (!expectation.matchHeaders(headers))\n        throw Error('Expected ' + expectation + ' with different headers\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.headers) + '\\nGOT:      ' +\n            prettyPrint(headers));\n\n      expectations.shift();\n\n      if (expectation.response) {\n        responses.push(function() {\n          var response = expectation.response(method, url, data, headers);\n          xhr.$$respHeaders = response[2];\n          callback(response[0], response[1], xhr.getAllResponseHeaders());\n        });\n        return;\n      }\n      wasExpected = true;\n    }\n\n    var i = -1, definition;\n    while ((definition = definitions[++i])) {\n      if (definition.match(method, url, data, headers || {})) {\n        if (definition.response) {\n          // if $browser specified, we do auto flush all requests\n          ($browser ? $browser.defer : responsesPush)(function() {\n            var response = definition.response(method, url, data, headers);\n            xhr.$$respHeaders = response[2];\n            callback(response[0], response[1], xhr.getAllResponseHeaders());\n          });\n        } else if (definition.passThrough) {\n          $delegate(method, url, data, callback, headers);\n        } else throw Error('No response defined !');\n        return;\n      }\n    }\n    throw wasExpected ?\n        Error('No response defined !') :\n        Error('Unexpected request: ' + method + ' ' + url + '\\n' +\n              (expectation ? 'Expected ' + expectation : 'No more request expected'));\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#when\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current definition.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.when = function(method, url, data, headers) {\n    var definition = new MockHttpExpectation(method, url, data, headers),\n        chain = {\n          respond: function(status, data, headers) {\n            definition.response = createResponse(status, data, headers);\n          }\n        };\n\n    if ($browser) {\n      chain.passThrough = function() {\n        definition.passThrough = true;\n      };\n    }\n\n    definitions.push(definition);\n    return chain;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for GET requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for HEAD requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for DELETE requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for POST requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for PUT requests.  For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for JSONP requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n  createShortMethods('when');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expect\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current expectation.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *  request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.expect = function(method, url, data, headers) {\n    var expectation = new MockHttpExpectation(method, url, data, headers);\n    expectations.push(expectation);\n    return {\n      respond: function(status, data, headers) {\n        expectation.response = createResponse(status, data, headers);\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for GET requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled. See #expect for more info.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for HEAD requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for DELETE requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for POST requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PUT requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPATCH\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PATCH requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for JSONP requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n  createShortMethods('expect');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#flush\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Flushes all pending requests using the trained responses.\n   *\n   * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,\n   *   all pending requests will be flushed. If there are no pending requests when the flush method\n   *   is called an exception is thrown (as this typically a sign of programming error).\n   */\n  $httpBackend.flush = function(count) {\n    if (!responses.length) throw Error('No pending request to flush !');\n\n    if (angular.isDefined(count)) {\n      while (count--) {\n        if (!responses.length) throw Error('No more pending request to flush !');\n        responses.shift()();\n      }\n    } else {\n      while (responses.length) {\n        responses.shift()();\n      }\n    }\n    $httpBackend.verifyNoOutstandingExpectation();\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingExpectation\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that all of the requests defined via the `expect` api were made. If any of the\n   * requests were not made, verifyNoOutstandingExpectation throws an exception.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyExpectations);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingExpectation = function() {\n    if (expectations.length) {\n      throw Error('Unsatisfied requests: ' + expectations.join(', '));\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingRequest\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that there are no outstanding requests that need to be flushed.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyNoOutstandingRequest);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingRequest = function() {\n    if (responses.length) {\n      throw Error('Unflushed requests: ' + responses.length);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#resetExpectations\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Resets all request expectations, but preserves all backend definitions. Typically, you would\n   * call resetExpectations during a multiple-phase test when you want to reuse the same instance of\n   * $httpBackend mock.\n   */\n  $httpBackend.resetExpectations = function() {\n    expectations.length = 0;\n    responses.length = 0;\n  };\n\n  return $httpBackend;\n\n\n  function createShortMethods(prefix) {\n    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {\n     $httpBackend[prefix + method] = function(url, headers) {\n       return $httpBackend[prefix](method, url, undefined, headers)\n     }\n    });\n\n    angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {\n      $httpBackend[prefix + method] = function(url, data, headers) {\n        return $httpBackend[prefix](method, url, data, headers)\n      }\n    });\n  }\n}\n\nfunction MockHttpExpectation(method, url, data, headers) {\n\n  this.data = data;\n  this.headers = headers;\n\n  this.match = function(m, u, d, h) {\n    if (method != m) return false;\n    if (!this.matchUrl(u)) return false;\n    if (angular.isDefined(d) && !this.matchData(d)) return false;\n    if (angular.isDefined(h) && !this.matchHeaders(h)) return false;\n    return true;\n  };\n\n  this.matchUrl = function(u) {\n    if (!url) return true;\n    if (angular.isFunction(url.test)) return url.test(u);\n    return url == u;\n  };\n\n  this.matchHeaders = function(h) {\n    if (angular.isUndefined(headers)) return true;\n    if (angular.isFunction(headers)) return headers(h);\n    return angular.equals(headers, h);\n  };\n\n  this.matchData = function(d) {\n    if (angular.isUndefined(data)) return true;\n    if (data && angular.isFunction(data.test)) return data.test(d);\n    if (data && !angular.isString(data)) return angular.toJson(data) == d;\n    return data == d;\n  };\n\n  this.toString = function() {\n    return method + ' ' + url;\n  };\n}\n\nfunction MockXhr() {\n\n  // hack for testing $http, $httpBackend\n  MockXhr.$$lastInstance = this;\n\n  this.open = function(method, url, async) {\n    this.$$method = method;\n    this.$$url = url;\n    this.$$async = async;\n    this.$$reqHeaders = {};\n    this.$$respHeaders = {};\n  };\n\n  this.send = function(data) {\n    this.$$data = data;\n  };\n\n  this.setRequestHeader = function(key, value) {\n    this.$$reqHeaders[key] = value;\n  };\n\n  this.getResponseHeader = function(name) {\n    // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last\n    var header = this.$$respHeaders[name];\n    if (header) return header;\n\n    name = angular.lowercase(name);\n    header = this.$$respHeaders[name];\n    if (header) return header;\n\n    header = undefined;\n    angular.forEach(this.$$respHeaders, function(headerVal, headerName) {\n      if (!header && angular.lowercase(headerName) == name) header = headerVal;\n    });\n    return header;\n  };\n\n  this.getAllResponseHeaders = function() {\n    var lines = [];\n\n    angular.forEach(this.$$respHeaders, function(value, key) {\n      lines.push(key + ': ' + value);\n    });\n    return lines.join('\\n');\n  };\n\n  this.abort = angular.noop;\n}\n\n\n/**\n * @ngdoc function\n * @name ngMock.$timeout\n * @description\n *\n * This service is just a simple decorator for {@link ng.$timeout $timeout} service\n * that adds a \"flush\" method.\n */\n\n/**\n * @ngdoc method\n * @name ngMock.$timeout#flush\n * @methodOf ngMock.$timeout\n * @description\n *\n * Flushes the queue of pending tasks.\n */\n\n/**\n *\n */\nangular.mock.$RootElementProvider = function() {\n  this.$get = function() {\n    return angular.element('<div ng-app></div>');\n  }\n};\n\n/**\n * @ngdoc overview\n * @name ngMock\n * @description\n *\n * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful\n * mocks to the {@link AUTO.$injector $injector}.\n */\nangular.module('ngMock', ['ng']).provider({\n  $browser: angular.mock.$BrowserProvider,\n  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,\n  $log: angular.mock.$LogProvider,\n  $httpBackend: angular.mock.$HttpBackendProvider,\n  $rootElement: angular.mock.$RootElementProvider\n}).config(function($provide) {\n  $provide.decorator('$timeout', function($delegate, $browser) {\n    $delegate.flush = function() {\n      $browser.defer.flush();\n    };\n    return $delegate;\n  });\n});\n\n\n/**\n * @ngdoc overview\n * @name ngMockE2E\n * @description\n *\n * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.\n * Currently there is only one mock present in this module -\n * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.\n */\nangular.module('ngMockE2E', ['ng']).config(function($provide) {\n  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);\n});\n\n/**\n * @ngdoc object\n * @name ngMockE2E.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of\n * applications that use the {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for unit testing please see\n * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.\n *\n * This implementation can be used to respond with static or dynamic responses via the `when` api\n * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the\n * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch\n * templates from a webserver).\n *\n * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application\n * is being developed with the real backend api replaced with a mock, it is often desirable for\n * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch\n * templates or static files from the webserver). To configure the backend with this behavior\n * use the `passThrough` request handler of `when` instead of `respond`.\n *\n * Additionally, we don't want to manually have to flush mocked out requests like we do during unit\n * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests\n * automatically, closely simulating the behavior of the XMLHttpRequest object.\n *\n * To setup the application to run with this http backend, you have to create a module that depends\n * on the `ngMockE2E` and your application modules and defines the fake backend:\n *\n * <pre>\n *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);\n *   myAppDev.run(function($httpBackend) {\n *     phones = [{name: 'phone1'}, {name: 'phone2'}];\n *\n *     // returns the current list of phones\n *     $httpBackend.whenGET('/phones').respond(phones);\n *\n *     // adds a new phone to the phones array\n *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {\n *       phones.push(angular.fromJSON(data));\n *     });\n *     $httpBackend.whenGET(/^\\/templates\\//).passThrough();\n *     //...\n *   });\n * </pre>\n *\n * Afterwards, bootstrap your app with this new module.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#when\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition.\n *\n * @param {string} method HTTP method.\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n *   object and returns true if the headers match the current definition.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n *\n *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n *    – The respond method takes a set of static data to be returned or a function that can return\n *    an array containing response status (number), response data (string) and response headers\n *    (Object).\n *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`\n *    handler, will be pass through to the real backend (an XHR request will be made to the\n *    server.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenGET\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for GET requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenHEAD\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for HEAD requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenDELETE\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for DELETE requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPOST\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for POST requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPUT\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PUT requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPATCH\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PATCH requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenJSONP\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for JSONP requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\nangular.mock.e2e = {};\nangular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];\n\n\nangular.mock.clearDataCache = function() {\n  var key,\n      cache = angular.element.cache;\n\n  for(key in cache) {\n    if (cache.hasOwnProperty(key)) {\n      var handle = cache[key].handle;\n\n      handle && angular.element(handle.elem).unbind();\n      delete cache[key];\n    }\n  }\n};\n\n\nwindow.jstestdriver && (function(window) {\n  /**\n   * Global method to output any number of objects into JSTD console. Useful for debugging.\n   */\n  window.dump = function() {\n    var args = [];\n    angular.forEach(arguments, function(arg) {\n      args.push(angular.mock.dump(arg));\n    });\n    jstestdriver.console.log.apply(jstestdriver.console, args);\n    if (window.console) {\n      window.console.log.apply(window.console, args);\n    }\n  };\n})(window);\n\n\nwindow.jasmine && (function(window) {\n\n  afterEach(function() {\n    var spec = getCurrentSpec();\n    var injector = spec.$injector;\n\n    spec.$injector = null;\n    spec.$modules = null;\n\n    if (injector) {\n      injector.get('$rootElement').unbind();\n      injector.get('$browser').pollFns.length = 0;\n    }\n\n    angular.mock.clearDataCache();\n\n    // clean up jquery's fragment cache\n    angular.forEach(angular.element.fragments, function(val, key) {\n      delete angular.element.fragments[key];\n    });\n\n    MockXhr.$$lastInstance = null;\n\n    angular.forEach(angular.callbacks, function(val, key) {\n      delete angular.callbacks[key];\n    });\n    angular.callbacks.counter = 0;\n  });\n\n  function getCurrentSpec() {\n    return jasmine.getEnv().currentSpec;\n  }\n\n  function isSpecRunning() {\n    var spec = getCurrentSpec();\n    return spec && spec.queue.running;\n  }\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.module\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * This function registers a module configuration code. It collects the configuration information\n   * which will be used when the injector is created by {@link angular.mock.inject inject}.\n   *\n   * See {@link angular.mock.inject inject} for usage example\n   *\n   * @param {...(string|Function)} fns any number of modules which are represented as string\n   *        aliases or as anonymous module initialization functions. The modules are used to\n   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.\n   */\n  window.module = angular.mock.module = function() {\n    var moduleFns = Array.prototype.slice.call(arguments, 0);\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      if (spec.$injector) {\n        throw Error('Injector already created, can not register a module!');\n      } else {\n        var modules = spec.$modules || (spec.$modules = []);\n        angular.forEach(moduleFns, function(module) {\n          modules.push(module);\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.inject\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * The inject function wraps a function into an injectable function. The inject() creates new\n   * instance of {@link AUTO.$injector $injector} per test, which is then used for\n   * resolving references.\n   *\n   * See also {@link angular.mock.module module}\n   *\n   * Example of what a typical jasmine tests looks like with the inject method.\n   * <pre>\n   *\n   *   angular.module('myApplicationModule', [])\n   *       .value('mode', 'app')\n   *       .value('version', 'v1.0.1');\n   *\n   *\n   *   describe('MyApp', function() {\n   *\n   *     // You need to load modules that you want to test,\n   *     // it loads only the \"ng\" module by default.\n   *     beforeEach(module('myApplicationModule'));\n   *\n   *\n   *     // inject() is used to inject arguments of all given functions\n   *     it('should provide a version', inject(function(mode, version) {\n   *       expect(version).toEqual('v1.0.1');\n   *       expect(mode).toEqual('app');\n   *     }));\n   *\n   *\n   *     // The inject and module method can also be used inside of the it or beforeEach\n   *     it('should override a version and test the new version is injected', function() {\n   *       // module() takes functions or strings (module aliases)\n   *       module(function($provide) {\n   *         $provide.value('version', 'overridden'); // override version here\n   *       });\n   *\n   *       inject(function(version) {\n   *         expect(version).toEqual('overridden');\n   *       });\n   *     ));\n   *   });\n   *\n   * </pre>\n   *\n   * @param {...Function} fns any number of functions which will be injected using the injector.\n   */\n  window.inject = angular.mock.inject = function() {\n    var blockFns = Array.prototype.slice.call(arguments, 0);\n    var errorForStack = new Error('Declaration Location');\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      var modules = spec.$modules || [];\n      modules.unshift('ngMock');\n      modules.unshift('ng');\n      var injector = spec.$injector;\n      if (!injector) {\n        injector = spec.$injector = angular.injector(modules);\n      }\n      for(var i = 0, ii = blockFns.length; i < ii; i++) {\n        try {\n          injector.invoke(blockFns[i] || angular.noop, this);\n        } catch (e) {\n          if(e.stack) e.stack +=  '\\n' + errorForStack.stack;\n          throw e;\n        } finally {\n          errorForStack = null;\n        }\n      }\n    }\n  };\n})(window);\n"
  },
  {
    "path": "chapter2/recipe7/test/lib/angular/angular-scenario.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Mar 21 12:46:34 2012 -0700\n */\n(function( window, undefined ) {\n'use strict';\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.7.2\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in array && array[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n\t\tvar exec,\n\t\t\tbulk = key == null,\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\n\t\t// Sets many values\n\t\tif ( key && typeof key === \"object\" ) {\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n\t\t\t}\n\t\t\tchainable = 1;\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = pass === undefined && jQuery.isFunction( value );\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations only iterate when executing function values\n\t\t\t\tif ( exec ) {\n\t\t\t\t\texec = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn exec.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\n\t\t\t\t// Otherwise they run against the entire set\n\t\t\t\t} else {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor (; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchainable = 1;\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfired = true;\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar length = list.length;\n\t\t\t\t\tadd( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory || memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tfragment,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tpixelMargin: true\n\t};\n\n\t// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead\n\tjQuery.boxModel = support.boxModel = (document.compatMode === \"CSS1Compat\");\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor ( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\tfragment.removeChild( div );\n\n\t// Null elements to avoid leaks in IE\n\tfragment = select = opt = div = input = null;\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tmarginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,\n\t\t\tpaddingMarginBorderVisibility, paddingMarginBorder,\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tconMarginTop = 1;\n\t\tpaddingMarginBorder = \"padding:0;margin:0;border:\";\n\t\tpositionTopLeftWidthHeight = \"position:absolute;top:0;left:0;width:1px;height:1px;\";\n\t\tpaddingMarginBorderVisibility = paddingMarginBorder + \"0;visibility:hidden;\";\n\t\tstyle = \"style='\" + positionTopLeftWidthHeight + paddingMarginBorder + \"5px solid #000;\";\n\t\thtml = \"<div \" + style + \"display:block;'><div style='\" + paddingMarginBorder + \"0;display:block;overflow:hidden;'></div></div>\" +\n\t\t\t\"<table \" + style + \"' cellpadding='0' cellspacing='0'>\" +\n\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = paddingMarginBorderVisibility + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td style='\" + paddingMarginBorder + \"0;display:none'></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName( \"td\" );\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t// gets computed margin-right based on width of container. For more\n\t\t// info see bug #3333\n\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tmarginDiv = document.createElement( \"div\" );\n\t\t\tmarginDiv.style.width = \"0\";\n\t\t\tmarginDiv.style.marginRight = \"0\";\n\t\t\tdiv.style.width = \"2px\";\n\t\t\tdiv.appendChild( marginDiv );\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\t// (IE < 8 does this)\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.width = div.style.padding = \"1px\";\n\t\t\tdiv.style.border = 0;\n\t\t\tdiv.style.overflow = \"hidden\";\n\t\t\tdiv.style.display = \"inline\";\n\t\t\tdiv.style.zoom = 1;\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.style.overflow = \"visible\";\n\t\t\tdiv.innerHTML = \"<div style='width:5px;'></div>\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\t\t}\n\n\t\tdiv.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;\n\t\tdiv.innerHTML = html;\n\n\t\touter = div.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.style.marginTop = \"1%\";\n\t\t\tsupport.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== \"1%\";\n\t\t}\n\n\t\tif ( typeof container.style.zoom !== \"undefined\" ) {\n\t\t\tcontainer.style.zoom = 1;\n\t\t}\n\n\t\tbody.removeChild( container );\n\t\tmarginDiv = div = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\treturn support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ internalKey ] : internalKey;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ internalKey ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( internalKey );\n\t\t\t} else {\n\t\t\t\telem[ internalKey ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, part, attr, name, l,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = elem.attributes;\n\t\t\t\t\tfor ( l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split( \".\", 2 );\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\t\tpart = parts[1] + \"!\";\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\tdata = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\tif ( data === undefined && elem ) {\n\t\t\t\t\tdata = jQuery.data( elem, key );\n\t\t\t\t\tdata = dataAttr( elem, key, data );\n\t\t\t\t}\n\n\t\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\t\tdata;\n\t\t\t}\n\n\t\t\tparts[1] = value;\n\t\t\tthis.each(function() {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.triggerHandler( \"setData\" + part, parts );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + part, parts );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, false );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\thooks = {};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( object );\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, l, isBool,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\t\t\tattrNames = value.toLowerCase().split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tisBool = rboolean.test( name );\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\t// Do not do this for boolean attributes (see #10870)\n\t\t\t\t\tif ( !isBool ) {\n\t\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\t}\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( isBool && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true,\n\t\tcoords: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = \"\" + value );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+)?\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\tvar attrs = elem.attributes || {};\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || (attrs.id || {}).value === m[2]) &&\n\t\t\t(!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tquick: selector && quickParse( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t ( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\told = null;\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\tspecial = jQuery.event.special[ event.type ] || {},\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n\t\t\t// Pregenerate a single jQuery object for reuse with .is()\n\t\t\tjqcur = jQuery(this);\n\t\t\tjqcur.context = this.ownerDocument || this;\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process events on disabled elements (#6911, #8165)\n\t\t\t\tif ( cur.disabled !== true ) {\n\t\t\t\t\tselMatch = {};\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tjqcur[0] = cur;\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\t\tselMatch[ sel ] = (\n\t\t\t\t\t\t\t\thandleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\tret;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\t\t\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\telem._change_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) { // && selector != null\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( var type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\n\t\t\tparts.push( m[1] );\n\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\t\t/* falls through */\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n// Expose origPOS\n// \"global\" as in regardless of relation to brackets/parens\nExpr.match.globalPOS = origPOS;\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry {\n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.globalPOS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\tPOS.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery.clean(arguments) );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tnull;\n\t\t\t}\n\n\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, function( i, elem ) {\n\t\t\t\t\tif ( elem.src ) {\n\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\turl: elem.src,\n\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\tdataType: \"script\"\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\n\t// IE blanks contents when cloning scripts\n\t} else if ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdest.text = src.text;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n\n\t// Clear flags for bubbling special change/submit events, they must\n\t// be reattached when the newly cloned events are first activated\n\tdest.removeAttribute( \"_submit_attached\" );\n\tdest.removeAttribute( \"_change_attached\" );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n\t// Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n\tvar div = document.createElement( \"div\" );\n\tsafeFragment.appendChild( div );\n\n\tdiv.innerHTML = elem.outerHTML;\n\treturn div.firstChild;\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t\tclone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ?\n\t\t\t\telem.cloneNode( true ) :\n\t\t\t\tshimCloneNode( elem );\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType, script, j,\n\t\t\t\tret = [];\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\"),\n\t\t\t\t\t\tsafeChildNodes = safeFragment.childNodes,\n\t\t\t\t\t\tremove;\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\n\t\t\t\t\t// Clear elements from DocumentFragment (safeFragment or otherwise)\n\t\t\t\t\t// to avoid hoarding elements. Fixes #11356\n\t\t\t\t\tif ( div ) {\n\t\t\t\t\t\tdiv.parentNode.removeChild( div );\n\n\t\t\t\t\t\t// Guard against -1 index exceptions in FF3.6\n\t\t\t\t\t\tif ( safeChildNodes.length > 0 ) {\n\t\t\t\t\t\t\tremove = safeChildNodes[ safeChildNodes.length - 1 ];\n\n\t\t\t\t\t\t\tif ( remove && remove.parentNode ) {\n\t\t\t\t\t\t\t\tremove.parentNode.removeChild( remove );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tscript = ret[i];\n\t\t\t\tif ( scripts && jQuery.nodeName( script, \"script\" ) && (!script.type || rscriptType.test( script.type )) ) {\n\t\t\t\t\tscripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( script.nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( script.getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( script );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnum = /^[\\-+]?(?:\\d*\\.)?\\d+$/i,\n\trnumnonpx = /^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\trmargin = /^margin/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\n\t// order is important!\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\treturn jQuery.access( this, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t}, name, value, arguments.length > 1 );\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {},\n\t\t\tret, name;\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// DEPRECATED in 1.3, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle, width,\n\t\t\tstyle = elem.style;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( (defaultView = elem.ownerDocument.defaultView) &&\n\t\t\t\t(computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// WebKit uses \"computed value (percentage if specified)\" instead of \"used value\" for margins\n\t\t// which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {\n\t\t\twidth = style.width;\n\t\t\tstyle.width = ret;\n\t\t\tret = computedStyle.width;\n\t\t\tstyle.width = width;\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( rnumnonpx.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\ti = name === \"width\" ? 1 : 0,\n\t\tlen = 4;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tfor ( ; i < len; i += 2 ) {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ];\n\t}\n\n\t// Computed unit is not pixels. Stop here and return.\n\tif ( rnumnonpx.test(val) ) {\n\t\treturn val;\n\t}\n\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tfor ( ; i < len; i += 2 ) {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val + \"px\";\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\treturn jQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\treturn rnum.test( value ) ?\n\t\t\t\tvalue + \"px\" :\n\t\t\t\tvalue;\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\treturn curCSS( elem, \"margin-right\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i,\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n\t\t\t\texpanded = {};\n\n\t\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n});\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = ( typeof s.data === \"string\" ) && /^application\\/x\\-www\\-form\\-urlencoded/.test( s.contentType );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t} catch( _ ) {\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( (display === \"\" && jQuery.css(elem, \"display\") === \"none\") ||\n\t\t\t\t\t\t!jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e, hooks, replace,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\t// first pass over propertys to expand / normalize\n\t\t\tfor ( p in prop ) {\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tif ( ( hooks = jQuery.cssHooks[ name ] ) && \"expand\" in hooks ) {\n\t\t\t\t\treplace = hooks.expand( prop[ name ] );\n\t\t\t\t\tdelete prop[ name ];\n\n\t\t\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t\t\t// also - reusing 'p' from above because we have the correct \"name\"\n\t\t\t\t\tfor ( p in replace ) {\n\t\t\t\t\t\tif ( ! ( p in prop ) ) {\n\t\t\t\t\t\t\tprop[ p ] = replace[ p ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( name in prop ) {\n\t\t\t\tval = prop[ name ];\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, index ) {\n\t\t\t\tvar hooks = data[ index ];\n\t\t\t\tjQuery.removeData( elem, index, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n\t\t\t\tstopQueue( this, data, index );\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ index ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ index ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p ) {\n\t\t\treturn p;\n\t\t},\n\t\tswing: function( p ) {\n\t\t\treturn ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tif ( self.options.hide ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t\t} else if ( self.options.show ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.end );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Ensure props that can't be negative don't go there on undershoot easing\njQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {\n\t// exclude marginTop, marginLeft, marginBottom and marginRight from this list\n\tif ( prop.indexOf( \"margin\" ) ) {\n\t\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( jQuery.support.boxModel ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar getOffset,\n\trtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tgetOffset = function( elem, doc, docElem, box ) {\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow( doc ),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tgetOffset = function( elem, doc, docElem ) {\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar elem = this[0],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn null;\n\t}\n\n\tif ( elem === doc.body ) {\n\t\treturn jQuery.offset.bodyOffset( elem );\n\t}\n\n\treturn getOffset( elem, doc, doc.documentElement );\n};\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t top ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tvar clientProp = \"client\" + name,\n\t\tscrollProp = \"scroll\" + name,\n\t\toffsetProp = \"offset\" + name;\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( value ) {\n\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\tvar doc, docElemProp, orig, ret;\n\n\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\t\tdoc = elem.document;\n\t\t\t\tdocElemProp = doc.documentElement[ clientProp ];\n\t\t\t\treturn jQuery.support.boxModel && docElemProp ||\n\t\t\t\t\tdoc.body && doc.body[ clientProp ] || docElemProp;\n\t\t\t}\n\n\t\t\t// Get document width or height\n\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t// when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]\n\t\t\t\t// so we can't use max, as it'll choose the incorrect offset[Width/Height]\n\t\t\t\t// instead we use the correct client[Width/Height]\n\t\t\t\t// support:IE6\n\t\t\t\tif ( doc[ clientProp ] >= doc[ scrollProp ] ) {\n\t\t\t\t\treturn doc[ clientProp ];\n\t\t\t\t}\n\n\t\t\t\treturn Math.max(\n\t\t\t\t\telem.body[ scrollProp ], doc[ scrollProp ],\n\t\t\t\t\telem.body[ offsetProp ], doc[ offsetProp ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get width or height on the element\n\t\t\tif ( value === undefined ) {\n\t\t\t\torig = jQuery.css( elem, type );\n\t\t\t\tret = parseFloat( orig );\n\t\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\t\t\t}\n\n\t\t\t// Set the width or height on the element\n\t\t\tjQuery( elem ).css( type, value );\n\t\t}, type, value, arguments.length, null );\n\t};\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );\n/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document){\n  var _jQuery = window.jQuery.noConflict(true);\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n\n/**\n * Setup file for the Scenario.\n * Must be first in the compilation/bootstrap list.\n */\n\n// Public namespace\nangular.scenario = angular.scenario || {};\n\n/**\n * Defines a new output format.\n *\n * @param {string} name the name of the new output format\n * @param {function()} fn function(context, runner) that generates the output\n */\nangular.scenario.output = angular.scenario.output || function(name, fn) {\n  angular.scenario.output[name] = fn;\n};\n\n/**\n * Defines a new DSL statement. If your factory function returns a Future\n * it's returned, otherwise the result is assumed to be a map of functions\n * for chaining. Chained functions are subject to the same rules.\n *\n * Note: All functions on the chain are bound to the chain scope so values\n *   set on \"this\" in your statement function are available in the chained\n *   functions.\n *\n * @param {string} name The name of the statement\n * @param {function()} fn Factory function(), return a function for\n *  the statement.\n */\nangular.scenario.dsl = angular.scenario.dsl || function(name, fn) {\n  angular.scenario.dsl[name] = function() {\n    function executeStatement(statement, args) {\n      var result = statement.apply(this, args);\n      if (angular.isFunction(result) || result instanceof angular.scenario.Future)\n        return result;\n      var self = this;\n      var chain = angular.extend({}, result);\n      angular.forEach(chain, function(value, name) {\n        if (angular.isFunction(value)) {\n          chain[name] = function() {\n            return executeStatement.call(self, value, arguments);\n          };\n        } else {\n          chain[name] = value;\n        }\n      });\n      return chain;\n    }\n    var statement = fn.apply(this, arguments);\n    return function() {\n      return executeStatement.call(this, statement, arguments);\n    };\n  };\n};\n\n/**\n * Defines a new matcher for use with the expects() statement. The value\n * this.actual (like in Jasmine) is available in your matcher to compare\n * against. Your function should return a boolean. The future is automatically\n * created for you.\n *\n * @param {string} name The name of the matcher\n * @param {function()} fn The matching function(expected).\n */\nangular.scenario.matcher = angular.scenario.matcher || function(name, fn) {\n  angular.scenario.matcher[name] = function(expected) {\n    var prefix = 'expect ' + this.future.name + ' ';\n    if (this.inverse) {\n      prefix += 'not ';\n    }\n    var self = this;\n    this.addFuture(prefix + name + ' ' + angular.toJson(expected),\n      function(done) {\n        var error;\n        self.actual = self.future.value;\n        if ((self.inverse && fn.call(self, expected)) ||\n            (!self.inverse && !fn.call(self, expected))) {\n          error = 'expected ' + angular.toJson(expected) +\n            ' but was ' + angular.toJson(self.actual);\n        }\n        done(error);\n    });\n  };\n};\n\n/**\n * Initialize the scenario runner and run !\n *\n * Access global window and document object\n * Access $runner through closure\n *\n * @param {Object=} config Config options\n */\nangular.scenario.setUpAndRun = function(config) {\n  var href = window.location.href;\n  var body = _jQuery(document.body);\n  var output = [];\n  var objModel = new angular.scenario.ObjectModel($runner);\n\n  if (config && config.scenario_output) {\n    output = config.scenario_output.split(',');\n  }\n\n  angular.forEach(angular.scenario.output, function(fn, name) {\n    if (!output.length || indexOf(output,name) != -1) {\n      var context = body.append('<div></div>').find('div:last');\n      context.attr('id', name);\n      fn.call({}, context, $runner, objModel);\n    }\n  });\n\n  if (!/^http/.test(href) && !/^https/.test(href)) {\n    body.append('<p id=\"system-error\"></p>');\n    body.find('#system-error').text(\n      'Scenario runner must be run using http or https. The protocol ' +\n      href.split(':')[0] + ':// is not supported.'\n    );\n    return;\n  }\n\n  var appFrame = body.append('<div id=\"application\"></div>').find('#application');\n  var application = new angular.scenario.Application(appFrame);\n\n  $runner.on('RunnerEnd', function() {\n    appFrame.css('display', 'none');\n    appFrame.find('iframe').attr('src', 'about:blank');\n  });\n\n  $runner.on('RunnerError', function(error) {\n    if (window.console) {\n      console.log(formatException(error));\n    } else {\n      // Do something for IE\n      alert(error);\n    }\n  });\n\n  $runner.run(application);\n};\n\n/**\n * Iterates through list with iterator function that must call the\n * continueFunction to continute iterating.\n *\n * @param {Array} list list to iterate over\n * @param {function()} iterator Callback function(value, continueFunction)\n * @param {function()} done Callback function(error, result) called when\n *   iteration finishes or an error occurs.\n */\nfunction asyncForEach(list, iterator, done) {\n  var i = 0;\n  function loop(error, index) {\n    if (index && index > i) {\n      i = index;\n    }\n    if (error || i >= list.length) {\n      done(error);\n    } else {\n      try {\n        iterator(list[i++], loop);\n      } catch (e) {\n        done(e);\n      }\n    }\n  }\n  loop();\n}\n\n/**\n * Formats an exception into a string with the stack trace, but limits\n * to a specific line length.\n *\n * @param {Object} error The exception to format, can be anything throwable\n * @param {Number=} [maxStackLines=5] max lines of the stack trace to include\n *  default is 5.\n */\nfunction formatException(error, maxStackLines) {\n  maxStackLines = maxStackLines || 5;\n  var message = error.toString();\n  if (error.stack) {\n    var stack = error.stack.split('\\n');\n    if (stack[0].indexOf(message) === -1) {\n      maxStackLines++;\n      stack.unshift(error.message);\n    }\n    message = stack.slice(0, maxStackLines).join('\\n');\n  }\n  return message;\n}\n\n/**\n * Returns a function that gets the file name and line number from a\n * location in the stack if available based on the call site.\n *\n * Note: this returns another function because accessing .stack is very\n * expensive in Chrome.\n *\n * @param {Number} offset Number of stack lines to skip\n */\nfunction callerFile(offset) {\n  var error = new Error();\n\n  return function() {\n    var line = (error.stack || '').split('\\n')[offset];\n\n    // Clean up the stack trace line\n    if (line) {\n      if (line.indexOf('@') !== -1) {\n        // Firefox\n        line = line.substring(line.indexOf('@')+1);\n      } else {\n        // Chrome\n        line = line.substring(line.indexOf('(')+1).replace(')', '');\n      }\n    }\n\n    return line || '';\n  };\n}\n\n/**\n * Triggers a browser event. Attempts to choose the right event if one is\n * not specified.\n *\n * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement\n * @param {string} type Optional event type.\n * @param {Array.<string>=} keys Optional list of pressed keys\n *        (valid values: 'alt', 'meta', 'shift', 'ctrl')\n */\nfunction browserTrigger(element, type, keys) {\n  if (element && !element.nodeName) element = element[0];\n  if (!element) return;\n  if (!type) {\n    type = {\n        'text':            'change',\n        'textarea':        'change',\n        'hidden':          'change',\n        'password':        'change',\n        'button':          'click',\n        'submit':          'click',\n        'reset':           'click',\n        'image':           'click',\n        'checkbox':        'click',\n        'radio':           'click',\n        'select-one':      'change',\n        'select-multiple': 'change'\n    }[lowercase(element.type)] || 'click';\n  }\n  if (lowercase(nodeName_(element)) == 'option') {\n    element.parentNode.value = element.value;\n    element = element.parentNode;\n    type = 'change';\n  }\n\n  keys = keys || [];\n  function pressed(key) {\n    return indexOf(keys, key) !== -1;\n  }\n\n  if (msie < 9) {\n    switch(element.type) {\n      case 'radio':\n      case 'checkbox':\n        element.checked = !element.checked;\n        break;\n    }\n    // WTF!!! Error: Unspecified error.\n    // Don't know why, but some elements when detached seem to be in inconsistent state and\n    // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)\n    // forcing the browser to compute the element position (by reading its CSS)\n    // puts the element in consistent state.\n    element.style.posLeft;\n\n    // TODO(vojta): create event objects with pressed keys to get it working on IE<9\n    var ret = element.fireEvent('on' + type);\n    if (lowercase(element.type) == 'submit') {\n      while(element) {\n        if (lowercase(element.nodeName) == 'form') {\n          element.fireEvent('onsubmit');\n          break;\n        }\n        element = element.parentNode;\n      }\n    }\n    return ret;\n  } else {\n    var evnt = document.createEvent('MouseEvents'),\n        originalPreventDefault = evnt.preventDefault,\n        iframe = _jQuery('#application iframe')[0],\n        appWindow = iframe ? iframe.contentWindow : window,\n        fakeProcessDefault = true,\n        finalProcessDefault,\n        angular = appWindow.angular || {};\n\n    // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208\n    angular['ff-684208-preventDefault'] = false;\n    evnt.preventDefault = function() {\n      fakeProcessDefault = false;\n      return originalPreventDefault.apply(evnt, arguments);\n    };\n\n    evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, pressed('ctrl'), pressed('alt'),\n                        pressed('shift'), pressed('meta'), 0, element);\n\n    element.dispatchEvent(evnt);\n    finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);\n\n    delete angular['ff-684208-preventDefault'];\n\n    return finalProcessDefault;\n  }\n}\n\n/**\n * Don't use the jQuery trigger method since it works incorrectly.\n *\n * jQuery notifies listeners and then changes the state of a checkbox and\n * does not create a real browser event. A real click changes the state of\n * the checkbox and then notifies listeners.\n *\n * To work around this we instead use our own handler that fires a real event.\n */\n(function(fn){\n  var parentTrigger = fn.trigger;\n  fn.trigger = function(type) {\n    if (/(click|change|keydown|blur|input)/.test(type)) {\n      var processDefaults = [];\n      this.each(function(index, node) {\n        processDefaults.push(browserTrigger(node, type));\n      });\n\n      // this is not compatible with jQuery - we return an array of returned values,\n      // so that scenario runner know whether JS code has preventDefault() of the event or not...\n      return processDefaults;\n    }\n    return parentTrigger.apply(this, arguments);\n  };\n})(_jQuery.fn);\n\n/**\n * Finds all bindings with the substring match of name and returns an\n * array of their values.\n *\n * @param {string} bindExp The name to match\n * @return {Array.<string>} String of binding values\n */\n_jQuery.fn.bindings = function(windowJquery, bindExp) {\n  var result = [], match,\n      bindSelector = '.ng-binding:visible';\n  if (angular.isString(bindExp)) {\n    bindExp = bindExp.replace(/\\s/g, '');\n    match = function (actualExp) {\n      if (actualExp) {\n        actualExp = actualExp.replace(/\\s/g, '');\n        if (actualExp == bindExp) return true;\n        if (actualExp.indexOf(bindExp) == 0) {\n          return actualExp.charAt(bindExp.length) == '|';\n        }\n      }\n    }\n  } else if (bindExp) {\n    match = function(actualExp) {\n      return actualExp && bindExp.exec(actualExp);\n    }\n  } else {\n    match = function(actualExp) {\n      return !!actualExp;\n    };\n  }\n  var selection = this.find(bindSelector);\n  if (this.is(bindSelector)) {\n    selection = selection.add(this);\n  }\n\n  function push(value) {\n    if (value == undefined) {\n      value = '';\n    } else if (typeof value != 'string') {\n      value = angular.toJson(value);\n    }\n    result.push('' + value);\n  }\n\n  selection.each(function() {\n    var element = windowJquery(this),\n        binding;\n    if (binding = element.data('$binding')) {\n      if (typeof binding == 'string') {\n        if (match(binding)) {\n          push(element.scope().$eval(binding));\n        }\n      } else {\n        if (!angular.isArray(binding)) {\n          binding = [binding];\n        }\n        for(var fns, j=0, jj=binding.length;  j<jj; j++) {\n          fns = binding[j];\n          if (fns.parts) {\n            fns = fns.parts;\n          } else {\n            fns = [fns];\n          }\n          for (var scope, fn, i = 0, ii = fns.length; i < ii; i++) {\n            if(match((fn = fns[i]).exp)) {\n              push(fn(scope = scope || element.scope()));\n            }\n          }\n        }\n      }\n    }\n  });\n  return result;\n};\n\n/**\n * Represents the application currently being tested and abstracts usage\n * of iframes or separate windows.\n *\n * @param {Object} context jQuery wrapper around HTML context.\n */\nangular.scenario.Application = function(context) {\n  this.context = context;\n  context.append(\n    '<h2>Current URL: <a href=\"about:blank\">None</a></h2>' +\n    '<div id=\"test-frames\"></div>'\n  );\n};\n\n/**\n * Gets the jQuery collection of frames. Don't use this directly because\n * frames may go stale.\n *\n * @private\n * @return {Object} jQuery collection\n */\nangular.scenario.Application.prototype.getFrame_ = function() {\n  return this.context.find('#test-frames iframe:last');\n};\n\n/**\n * Gets the window of the test runner frame. Always favor executeAction()\n * instead of this method since it prevents you from getting a stale window.\n *\n * @private\n * @return {Object} the window of the frame\n */\nangular.scenario.Application.prototype.getWindow_ = function() {\n  var contentWindow = this.getFrame_().prop('contentWindow');\n  if (!contentWindow)\n    throw 'Frame window is not accessible.';\n  return contentWindow;\n};\n\n/**\n * Changes the location of the frame.\n *\n * @param {string} url The URL. If it begins with a # then only the\n *   hash of the page is changed.\n * @param {function()} loadFn function($window, $document) Called when frame loads.\n * @param {function()} errorFn function(error) Called if any error when loading.\n */\nangular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorFn) {\n  var self = this;\n  var frame = this.getFrame_();\n  //TODO(esprehn): Refactor to use rethrow()\n  errorFn = errorFn || function(e) { throw e; };\n  if (url === 'about:blank') {\n    errorFn('Sandbox Error: Navigating to about:blank is not allowed.');\n  } else if (url.charAt(0) === '#') {\n    url = frame.attr('src').split('#')[0] + url;\n    frame.attr('src', url);\n    this.executeAction(loadFn);\n  } else {\n    frame.remove();\n    this.context.find('#test-frames').append('<iframe>');\n    frame = this.getFrame_();\n    frame.load(function() {\n      frame.unbind();\n      try {\n        self.executeAction(loadFn);\n      } catch (e) {\n        errorFn(e);\n      }\n    }).attr('src', url);\n  }\n  this.context.find('> h2 a').attr('href', url).text(url);\n};\n\n/**\n * Executes a function in the context of the tested application. Will wait\n * for all pending angular xhr requests before executing.\n *\n * @param {function()} action The callback to execute. function($window, $document)\n *  $document is a jQuery wrapped document.\n */\nangular.scenario.Application.prototype.executeAction = function(action) {\n  var self = this;\n  var $window = this.getWindow_();\n  if (!$window.document) {\n    throw 'Sandbox Error: Application document not accessible.';\n  }\n  if (!$window.angular) {\n    return action.call(this, $window, _jQuery($window.document));\n  }\n  angularInit($window.document, function(element) {\n    var $injector = $window.angular.element(element).injector();\n    var $element = _jQuery(element);\n\n    $element.injector = function() {\n      return $injector;\n    };\n\n    $injector.invoke(function($browser){\n      $browser.notifyWhenNoOutstandingRequests(function() {\n        action.call(self, $window, $element);\n      });\n    });\n  });\n};\n\n/**\n * The representation of define blocks. Don't used directly, instead use\n * define() in your tests.\n *\n * @param {string} descName Name of the block\n * @param {Object} parent describe or undefined if the root.\n */\nangular.scenario.Describe = function(descName, parent) {\n  this.only = parent && parent.only;\n  this.beforeEachFns = [];\n  this.afterEachFns = [];\n  this.its = [];\n  this.children = [];\n  this.name = descName;\n  this.parent = parent;\n  this.id = angular.scenario.Describe.id++;\n\n  /**\n   * Calls all before functions.\n   */\n  var beforeEachFns = this.beforeEachFns;\n  this.setupBefore = function() {\n    if (parent) parent.setupBefore.call(this);\n    angular.forEach(beforeEachFns, function(fn) { fn.call(this); }, this);\n  };\n\n  /**\n   * Calls all after functions.\n   */\n  var afterEachFns = this.afterEachFns;\n  this.setupAfter  = function() {\n    angular.forEach(afterEachFns, function(fn) { fn.call(this); }, this);\n    if (parent) parent.setupAfter.call(this);\n  };\n};\n\n// Shared Unique ID generator for every describe block\nangular.scenario.Describe.id = 0;\n\n// Shared Unique ID generator for every it (spec)\nangular.scenario.Describe.specId = 0;\n\n/**\n * Defines a block to execute before each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.beforeEach = function(body) {\n  this.beforeEachFns.push(body);\n};\n\n/**\n * Defines a block to execute after each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.afterEach = function(body) {\n  this.afterEachFns.push(body);\n};\n\n/**\n * Creates a new describe block that's a child of this one.\n *\n * @param {string} name Name of the block. Appended to the parent block's name.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.describe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Same as describe() but makes ddescribe blocks the only to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.ddescribe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  child.only = true;\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Use to disable a describe block.\n */\nangular.scenario.Describe.prototype.xdescribe = angular.noop;\n\n/**\n * Defines a test.\n *\n * @param {string} name Name of the test.\n * @param {function()} vody Body of the block.\n */\nangular.scenario.Describe.prototype.it = function(name, body) {\n  this.its.push({\n    id: angular.scenario.Describe.specId++,\n    definition: this,\n    only: this.only,\n    name: name,\n    before: this.setupBefore,\n    body: body,\n    after: this.setupAfter\n  });\n};\n\n/**\n * Same as it() but makes iit tests the only test to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.iit = function(name, body) {\n  this.it.apply(this, arguments);\n  this.its[this.its.length-1].only = true;\n};\n\n/**\n * Use to disable a test block.\n */\nangular.scenario.Describe.prototype.xit = angular.noop;\n\n/**\n * Gets an array of functions representing all the tests (recursively).\n * that can be executed with SpecRunner's.\n *\n * @return {Array<Object>} Array of it blocks {\n *   definition : Object // parent Describe\n *   only: boolean\n *   name: string\n *   before: Function\n *   body: Function\n *   after: Function\n *  }\n */\nangular.scenario.Describe.prototype.getSpecs = function() {\n  var specs = arguments[0] || [];\n  angular.forEach(this.children, function(child) {\n    child.getSpecs(specs);\n  });\n  angular.forEach(this.its, function(it) {\n    specs.push(it);\n  });\n  var only = [];\n  angular.forEach(specs, function(it) {\n    if (it.only) {\n      only.push(it);\n    }\n  });\n  return (only.length && only) || specs;\n};\n\n/**\n * A future action in a spec.\n *\n * @param {string} name of the future action\n * @param {function()} future callback(error, result)\n * @param {function()} Optional. function that returns the file/line number.\n */\nangular.scenario.Future = function(name, behavior, line) {\n  this.name = name;\n  this.behavior = behavior;\n  this.fulfilled = false;\n  this.value = undefined;\n  this.parser = angular.identity;\n  this.line = line || function() { return ''; };\n};\n\n/**\n * Executes the behavior of the closure.\n *\n * @param {function()} doneFn Callback function(error, result)\n */\nangular.scenario.Future.prototype.execute = function(doneFn) {\n  var self = this;\n  this.behavior(function(error, result) {\n    self.fulfilled = true;\n    if (result) {\n      try {\n        result = self.parser(result);\n      } catch(e) {\n        error = e;\n      }\n    }\n    self.value = error || result;\n    doneFn(error, result);\n  });\n};\n\n/**\n * Configures the future to convert it's final with a function fn(value)\n *\n * @param {function()} fn function(value) that returns the parsed value\n */\nangular.scenario.Future.prototype.parsedWith = function(fn) {\n  this.parser = fn;\n  return this;\n};\n\n/**\n * Configures the future to parse it's final value from JSON\n * into objects.\n */\nangular.scenario.Future.prototype.fromJson = function() {\n  return this.parsedWith(angular.fromJson);\n};\n\n/**\n * Configures the future to convert it's final value from objects\n * into JSON.\n */\nangular.scenario.Future.prototype.toJson = function() {\n  return this.parsedWith(angular.toJson);\n};\n\n/**\n * Maintains an object tree from the runner events.\n *\n * @param {Object} runner The scenario Runner instance to connect to.\n *\n * TODO(esprehn): Every output type creates one of these, but we probably\n *  want one global shared instance. Need to handle events better too\n *  so the HTML output doesn't need to do spec model.getSpec(spec.id)\n *  silliness.\n *\n * TODO(vojta) refactor on, emit methods (from all objects) - use inheritance\n */\nangular.scenario.ObjectModel = function(runner) {\n  var self = this;\n\n  this.specMap = {};\n  this.listeners = [];\n  this.value = {\n    name: '',\n    children: {}\n  };\n\n  runner.on('SpecBegin', function(spec) {\n    var block = self.value,\n        definitions = [];\n\n    angular.forEach(self.getDefinitionPath(spec), function(def) {\n      if (!block.children[def.name]) {\n        block.children[def.name] = {\n          id: def.id,\n          name: def.name,\n          children: {},\n          specs: {}\n        };\n      }\n      block = block.children[def.name];\n      definitions.push(def.name);\n    });\n\n    var it = self.specMap[spec.id] =\n             block.specs[spec.name] =\n             new angular.scenario.ObjectModel.Spec(spec.id, spec.name, definitions);\n\n    // forward the event\n    self.emit('SpecBegin', it);\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var it = self.getSpec(spec.id);\n    it.status = 'error';\n    it.error = error;\n\n    // forward the event\n    self.emit('SpecError', it, error);\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    complete(it);\n\n    // forward the event\n    self.emit('SpecEnd', it);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var it = self.getSpec(spec.id);\n    var step = new angular.scenario.ObjectModel.Step(step.name);\n    it.steps.push(step);\n\n    // forward the event\n    self.emit('StepBegin', it, step);\n  });\n\n  runner.on('StepEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    var step = it.getLastStep();\n    if (step.name !== step.name)\n      throw 'Events fired in the wrong order. Step names don\\'t match.';\n    complete(step);\n\n    // forward the event\n    self.emit('StepEnd', it, step);\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('failure', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepFailure', it, modelStep, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('error', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepError', it, modelStep, error);\n  });\n\n  runner.on('RunnerBegin', function() {\n    self.emit('RunnerBegin');\n  });\n  runner.on('RunnerEnd', function() {\n    self.emit('RunnerEnd');\n  });\n\n  function complete(item) {\n    item.endTime = new Date().getTime();\n    item.duration = item.endTime - item.startTime;\n    item.status = item.status || 'success';\n  }\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName Name of the event to add a handler for\n * @param {function()} listener Function that will be called when event is fired\n */\nangular.scenario.ObjectModel.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.ObjectModel.prototype.emit = function(eventName) {\n  var self = this,\n      args = Array.prototype.slice.call(arguments, 1),\n      eventName = eventName.toLowerCase();\n\n  if (this.listeners[eventName]) {\n    angular.forEach(this.listeners[eventName], function(listener) {\n      listener.apply(self, args);\n    });\n  }\n};\n\n/**\n * Computes the path of definition describe blocks that wrap around\n * this spec.\n *\n * @param spec Spec to compute the path for.\n * @return {Array<Describe>} The describe block path\n */\nangular.scenario.ObjectModel.prototype.getDefinitionPath = function(spec) {\n  var path = [];\n  var currentDefinition = spec.definition;\n  while (currentDefinition && currentDefinition.name) {\n    path.unshift(currentDefinition);\n    currentDefinition = currentDefinition.parent;\n  }\n  return path;\n};\n\n/**\n * Gets a spec by id.\n *\n * @param {string} The id of the spec to get the object for.\n * @return {Object} the Spec instance\n */\nangular.scenario.ObjectModel.prototype.getSpec = function(id) {\n  return this.specMap[id];\n};\n\n/**\n * A single it block.\n *\n * @param {string} id Id of the spec\n * @param {string} name Name of the spec\n * @param {Array<string>=} definitionNames List of all describe block names that wrap this spec\n */\nangular.scenario.ObjectModel.Spec = function(id, name, definitionNames) {\n  this.id = id;\n  this.name = name;\n  this.startTime = new Date().getTime();\n  this.steps = [];\n  this.fullDefinitionName = (definitionNames || []).join(' ');\n};\n\n/**\n * Adds a new step to the Spec.\n *\n * @param {string} step Name of the step (really name of the future)\n * @return {Object} the added step\n */\nangular.scenario.ObjectModel.Spec.prototype.addStep = function(name) {\n  var step = new angular.scenario.ObjectModel.Step(name);\n  this.steps.push(step);\n  return step;\n};\n\n/**\n * Gets the most recent step.\n *\n * @return {Object} the step\n */\nangular.scenario.ObjectModel.Spec.prototype.getLastStep = function() {\n  return this.steps[this.steps.length-1];\n};\n\n/**\n * Set status of the Spec from given Step\n *\n * @param {angular.scenario.ObjectModel.Step} step\n */\nangular.scenario.ObjectModel.Spec.prototype.setStatusFromStep = function(step) {\n  if (!this.status || step.status == 'error') {\n    this.status = step.status;\n    this.error = step.error;\n    this.line = step.line;\n  }\n};\n\n/**\n * A single step inside a Spec.\n *\n * @param {string} step Name of the step\n */\nangular.scenario.ObjectModel.Step = function(name) {\n  this.name = name;\n  this.startTime = new Date().getTime();\n};\n\n/**\n * Helper method for setting all error status related properties\n *\n * @param {string} status\n * @param {string} error\n * @param {string} line\n */\nangular.scenario.ObjectModel.Step.prototype.setErrorStatus = function(status, error, line) {\n  this.status = status;\n  this.error = error;\n  this.line = line;\n};\n\n/**\n * Runner for scenarios\n *\n * Has to be initialized before any test is loaded,\n * because it publishes the API into window (global space).\n */\nangular.scenario.Runner = function($window) {\n  this.listeners = [];\n  this.$window = $window;\n  this.rootDescribe = new angular.scenario.Describe();\n  this.currentDescribe = this.rootDescribe;\n  this.api = {\n    it: this.it,\n    iit: this.iit,\n    xit: angular.noop,\n    describe: this.describe,\n    ddescribe: this.ddescribe,\n    xdescribe: angular.noop,\n    beforeEach: this.beforeEach,\n    afterEach: this.afterEach\n  };\n  angular.forEach(this.api, angular.bind(this, function(fn, key) {\n    this.$window[key] = angular.bind(this, fn);\n  }));\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.Runner.prototype.emit = function(eventName) {\n  var self = this;\n  var args = Array.prototype.slice.call(arguments, 1);\n  eventName = eventName.toLowerCase();\n  if (!this.listeners[eventName])\n    return;\n  angular.forEach(this.listeners[eventName], function(listener) {\n    listener.apply(self, args);\n  });\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName The name of the event to add a handler for\n * @param {string} listener The fn(...) that takes the extra arguments from emit()\n */\nangular.scenario.Runner.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Defines a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.describe = function(name, body) {\n  var self = this;\n  this.currentDescribe.describe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Same as describe, but makes ddescribe the only blocks to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.ddescribe = function(name, body) {\n  var self = this;\n  this.currentDescribe.ddescribe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Defines a test in a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.it = function(name, body) {\n  this.currentDescribe.it(name, body);\n};\n\n/**\n * Same as it, but makes iit tests the only tests to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.iit = function(name, body) {\n  this.currentDescribe.iit(name, body);\n};\n\n/**\n * Defines a function to be called before each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.beforeEach = function(body) {\n  this.currentDescribe.beforeEach(body);\n};\n\n/**\n * Defines a function to be called after each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.afterEach = function(body) {\n  this.currentDescribe.afterEach(body);\n};\n\n/**\n * Creates a new spec runner.\n *\n * @private\n * @param {Object} scope parent scope\n */\nangular.scenario.Runner.prototype.createSpecRunner_ = function(scope) {\n  var child = scope.$new();\n  var Cls = angular.scenario.SpecRunner;\n\n  // Export all the methods to child scope manually as now we don't mess controllers with scopes\n  // TODO(vojta): refactor scenario runner so that these objects are not tightly coupled as current\n  for (var name in Cls.prototype)\n    child[name] = angular.bind(child, Cls.prototype[name]);\n\n  Cls.call(child);\n  return child;\n};\n\n/**\n * Runs all the loaded tests with the specified runner class on the\n * provided application.\n *\n * @param {angular.scenario.Application} application App to remote control.\n */\nangular.scenario.Runner.prototype.run = function(application) {\n  var self = this;\n  var $root = angular.injector(['ng']).get('$rootScope');\n  angular.extend($root, this);\n  angular.forEach(angular.scenario.Runner.prototype, function(fn, name) {\n    $root[name] = angular.bind(self, fn);\n  });\n  $root.application = application;\n  $root.emit('RunnerBegin');\n  asyncForEach(this.rootDescribe.getSpecs(), function(spec, specDone) {\n    var dslCache = {};\n    var runner = self.createSpecRunner_($root);\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      dslCache[key] = fn.call($root);\n    });\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      self.$window[key] = function() {\n        var line = callerFile(3);\n        var scope = runner.$new();\n\n        // Make the dsl accessible on the current chain\n        scope.dsl = {};\n        angular.forEach(dslCache, function(fn, key) {\n          scope.dsl[key] = function() {\n            return dslCache[key].apply(scope, arguments);\n          };\n        });\n\n        // Make these methods work on the current chain\n        scope.addFuture = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFuture.apply(scope, arguments);\n        };\n        scope.addFutureAction = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFutureAction.apply(scope, arguments);\n        };\n\n        return scope.dsl[key].apply(scope, arguments);\n      };\n    });\n    runner.run(spec, function() {\n      runner.$destroy();\n      specDone.apply(this, arguments);\n    });\n  },\n  function(error) {\n    if (error) {\n      self.emit('RunnerError', error);\n    }\n    self.emit('RunnerEnd');\n  });\n};\n\n/**\n * This class is the \"this\" of the it/beforeEach/afterEach method.\n * Responsibilities:\n *   - \"this\" for it/beforeEach/afterEach\n *   - keep state for single it/beforeEach/afterEach execution\n *   - keep track of all of the futures to execute\n *   - run single spec (execute each future)\n */\nangular.scenario.SpecRunner = function() {\n  this.futures = [];\n  this.afterIndex = 0;\n};\n\n/**\n * Executes a spec which is an it block with associated before/after functions\n * based on the describe nesting.\n *\n * @param {Object} spec A spec object\n * @param {function()} specDone function that is called when the spec finshes. Function(error, index)\n */\nangular.scenario.SpecRunner.prototype.run = function(spec, specDone) {\n  var self = this;\n  this.spec = spec;\n\n  this.emit('SpecBegin', spec);\n\n  try {\n    spec.before.call(this);\n    spec.body.call(this);\n    this.afterIndex = this.futures.length;\n    spec.after.call(this);\n  } catch (e) {\n    this.emit('SpecError', spec, e);\n    this.emit('SpecEnd', spec);\n    specDone();\n    return;\n  }\n\n  var handleError = function(error, done) {\n    if (self.error) {\n      return done();\n    }\n    self.error = true;\n    done(null, self.afterIndex);\n  };\n\n  asyncForEach(\n    this.futures,\n    function(future, futureDone) {\n      self.step = future;\n      self.emit('StepBegin', spec, future);\n      try {\n        future.execute(function(error) {\n          if (error) {\n            self.emit('StepFailure', spec, future, error);\n            self.emit('StepEnd', spec, future);\n            return handleError(error, futureDone);\n          }\n          self.emit('StepEnd', spec, future);\n          self.$window.setTimeout(function() { futureDone(); }, 0);\n        });\n      } catch (e) {\n        self.emit('StepError', spec, future, e);\n        self.emit('StepEnd', spec, future);\n        handleError(e, futureDone);\n      }\n    },\n    function(e) {\n      if (e) {\n        self.emit('SpecError', spec, e);\n      }\n      self.emit('SpecEnd', spec);\n      // Call done in a timeout so exceptions don't recursively\n      // call this function\n      self.$window.setTimeout(function() { specDone(); }, 0);\n    }\n  );\n};\n\n/**\n * Adds a new future action.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFuture = function(name, behavior, line) {\n  var future = new angular.scenario.Future(name, angular.bind(this, behavior), line);\n  this.futures.push(future);\n  return future;\n};\n\n/**\n * Adds a new future action to be executed on the application window.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior, line) {\n  var self = this;\n  var NG = /\\[ng\\\\\\:/;\n  return this.addFuture(name, function(done) {\n    this.application.executeAction(function($window, $document) {\n\n      //TODO(esprehn): Refactor this so it doesn't need to be in here.\n      $document.elements = function(selector) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        selector = (self.selector || '') + ' ' + (selector || '');\n        selector = _jQuery.trim(selector) || '*';\n        angular.forEach(args, function(value, index) {\n          selector = selector.replace('$' + (index + 1), value);\n        });\n        var result = $document.find(selector);\n        if (selector.match(NG)) {\n          angular.forEach(['[ng-','[data-ng-','[x-ng-'], function(value, index){\n            result = result.add(selector.replace(NG, value), $document);\n          });\n        }\n        if (!result.length) {\n          throw {\n            type: 'selector',\n            message: 'Selector ' + selector + ' did not match any elements.'\n          };\n        }\n\n        return result;\n      };\n\n      try {\n        behavior.call(self, $window, $document, done);\n      } catch(e) {\n        if (e.type && e.type === 'selector') {\n          done(e.message);\n        } else {\n          throw e;\n        }\n      }\n    });\n  }, line);\n};\n\n/**\n * Shared DSL statements that are useful to all scenarios.\n */\n\n /**\n * Usage:\n *    pause() pauses until you call resume() in the console\n */\nangular.scenario.dsl('pause', function() {\n  return function() {\n    return this.addFuture('pausing for you to resume', function(done) {\n      this.emit('InteractivePause', this.spec, this.step);\n      this.$window.resume = function() { done(); };\n    });\n  };\n});\n\n/**\n * Usage:\n *    sleep(seconds) pauses the test for specified number of seconds\n */\nangular.scenario.dsl('sleep', function() {\n  return function(time) {\n    return this.addFuture('sleep for ' + time + ' seconds', function(done) {\n      this.$window.setTimeout(function() { done(null, time * 1000); }, time * 1000);\n    });\n  };\n});\n\n/**\n * Usage:\n *    browser().navigateTo(url) Loads the url into the frame\n *    browser().navigateTo(url, fn) where fn(url) is called and returns the URL to navigate to\n *    browser().reload() refresh the page (reload the same URL)\n *    browser().window.href() window.location.href\n *    browser().window.path() window.location.pathname\n *    browser().window.search() window.location.search\n *    browser().window.hash() window.location.hash without # prefix\n *    browser().location().url() see ng.$location#url\n *    browser().location().path() see ng.$location#path\n *    browser().location().search() see ng.$location#search\n *    browser().location().hash() see ng.$location#hash\n */\nangular.scenario.dsl('browser', function() {\n  var chain = {};\n\n  chain.navigateTo = function(url, delegate) {\n    var application = this.application;\n    return this.addFuture(\"browser navigate to '\" + url + \"'\", function(done) {\n      if (delegate) {\n        url = delegate.call(this, url);\n      }\n      application.navigateTo(url, function() {\n        done(null, url);\n      }, done);\n    });\n  };\n\n  chain.reload = function() {\n    var application = this.application;\n    return this.addFutureAction('browser reload', function($window, $document, done) {\n      var href = $window.location.href;\n      application.navigateTo(href, function() {\n        done(null, href);\n      }, done);\n    });\n  };\n\n  chain.window = function() {\n    var api = {};\n\n    api.href = function() {\n      return this.addFutureAction('window.location.href', function($window, $document, done) {\n        done(null, $window.location.href);\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('window.location.path', function($window, $document, done) {\n        done(null, $window.location.pathname);\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('window.location.search', function($window, $document, done) {\n        done(null, $window.location.search);\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('window.location.hash', function($window, $document, done) {\n        done(null, $window.location.hash.replace('#', ''));\n      });\n    };\n\n    return api;\n  };\n\n  chain.location = function() {\n    var api = {};\n\n    api.url = function() {\n      return this.addFutureAction('$location.url()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').url());\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('$location.path()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').path());\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('$location.search()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').search());\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('$location.hash()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').hash());\n      });\n    };\n\n    return api;\n  };\n\n  return function() {\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    expect(future).{matcher} where matcher is one of the matchers defined\n *    with angular.scenario.matcher\n *\n * ex. expect(binding(\"name\")).toEqual(\"Elliott\")\n */\nangular.scenario.dsl('expect', function() {\n  var chain = angular.extend({}, angular.scenario.matcher);\n\n  chain.not = function() {\n    this.inverse = true;\n    return chain;\n  };\n\n  return function(future) {\n    this.future = future;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    using(selector, label) scopes the next DSL element selection\n *\n * ex.\n *   using('#foo', \"'Foo' text field\").input('bar')\n */\nangular.scenario.dsl('using', function() {\n  return function(selector, label) {\n    this.selector = _jQuery.trim((this.selector||'') + ' ' + selector);\n    if (angular.isString(label) && label.length) {\n      this.label = label + ' ( ' + this.selector + ' )';\n    } else {\n      this.label = this.selector;\n    }\n    return this.dsl;\n  };\n});\n\n/**\n * Usage:\n *    binding(name) returns the value of the first matching binding\n */\nangular.scenario.dsl('binding', function() {\n  return function(name) {\n    return this.addFutureAction(\"select binding '\" + name + \"'\", function($window, $document, done) {\n      var values = $document.elements().bindings($window.angular.element, name);\n      if (!values.length) {\n        return done(\"Binding selector '\" + name + \"' did not match.\");\n      }\n      done(null, values[0]);\n    });\n  };\n});\n\n/**\n * Usage:\n *    input(name).enter(value) enters value in input with specified name\n *    input(name).check() checks checkbox\n *    input(name).select(value) selects the radio button with specified name/value\n *    input(name).val() returns the value of the input.\n */\nangular.scenario.dsl('input', function() {\n  var chain = {};\n  var supportInputEvent =  'oninput' in document.createElement('div') && msie != 9;\n\n  chain.enter = function(value, event) {\n    return this.addFutureAction(\"input '\" + this.name + \"' enter '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      input.val(value);\n      input.trigger(event || (supportInputEvent ? 'input' : 'change'));\n      done();\n    });\n  };\n\n  chain.check = function() {\n    return this.addFutureAction(\"checkbox '\" + this.name + \"' toggle\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':checkbox');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.select = function(value) {\n    return this.addFutureAction(\"radio button '\" + this.name + \"' toggle '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.\n        elements('[ng\\\\:model=\"$1\"][value=\"$2\"]', this.name, value).filter(':radio');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.val = function() {\n    return this.addFutureAction(\"return input val\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      done(null,input.val());\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n\n/**\n * Usage:\n *    repeater('#products table', 'Product List').count() number of rows\n *    repeater('#products table', 'Product List').row(1) all bindings in row as an array\n *    repeater('#products table', 'Product List').column('product.name') all values across all rows in an array\n */\nangular.scenario.dsl('repeater', function() {\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.column = function(binding) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' column '\" + binding + \"'\", function($window, $document, done) {\n      done(null, $document.elements().bindings($window.angular.element, binding));\n    });\n  };\n\n  chain.row = function(index) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' row '\" + index + \"'\", function($window, $document, done) {\n      var matches = $document.elements().slice(index, index + 1);\n      if (!matches.length)\n        return done('row ' + index + ' out of bounds');\n      done(null, matches.bindings($window.angular.element));\n    });\n  };\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    select(name).option('value') select one option\n *    select(name).options('value1', 'value2', ...) select options from a multi select\n */\nangular.scenario.dsl('select', function() {\n  var chain = {};\n\n  chain.option = function(value) {\n    return this.addFutureAction(\"select '\" + this.name + \"' option '\" + value + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[ng\\\\:model=\"$1\"]', this.name);\n      var option = select.find('option[value=\"' + value + '\"]');\n      if (option.length) {\n        select.val(value);\n      } else {\n        option = select.find('option:contains(\"' + value + '\")');\n        if (option.length) {\n          select.val(option.val());\n        }\n      }\n      select.trigger('change');\n      done();\n    });\n  };\n\n  chain.options = function() {\n    var values = arguments;\n    return this.addFutureAction(\"select '\" + this.name + \"' options '\" + values + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[multiple][ng\\\\:model=\"$1\"]', this.name);\n      select.val(values);\n      select.trigger('change');\n      done();\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    element(selector, label).count() get the number of elements that match selector\n *    element(selector, label).click() clicks an element\n *    element(selector, label).query(fn) executes fn(selectedElements, done)\n *    element(selector, label).{method}() gets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(value) sets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(key) gets the value (as defined by jQuery, ex. attr)\n *    element(selector, label).{method}(key, value) sets the value (as defined by jQuery, ex. attr)\n */\nangular.scenario.dsl('element', function() {\n  var KEY_VALUE_METHODS = ['attr', 'css', 'prop'];\n  var VALUE_METHODS = [\n    'val', 'text', 'html', 'height', 'innerHeight', 'outerHeight', 'width',\n    'innerWidth', 'outerWidth', 'position', 'scrollLeft', 'scrollTop', 'offset'\n  ];\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.click = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' click\", function($window, $document, done) {\n      var elements = $document.elements();\n      var href = elements.attr('href');\n      var eventProcessDefault = elements.trigger('click')[0];\n\n      if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {\n        this.application.navigateTo(href, function() {\n          done();\n        }, done);\n      } else {\n        done();\n      }\n    });\n  };\n\n  chain.query = function(fn) {\n    return this.addFutureAction('element ' + this.label + ' custom query', function($window, $document, done) {\n      fn.call(this, $document.elements(), done);\n    });\n  };\n\n  angular.forEach(KEY_VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(name, value) {\n      var args = arguments,\n          futureName = (args.length == 1)\n              ? \"element '\" + this.label + \"' get \" + methodName + \" '\" + name + \"'\"\n              : \"element '\" + this.label + \"' set \" + methodName + \" '\" + name + \"' to \" + \"'\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  angular.forEach(VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(value) {\n      var args = arguments,\n          futureName = (args.length == 0)\n              ? \"element '\" + this.label + \"' \" + methodName\n              : futureName = \"element '\" + this.label + \"' set \" + methodName + \" to '\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Matchers for implementing specs. Follows the Jasmine spec conventions.\n */\n\nangular.scenario.matcher('toEqual', function(expected) {\n  return angular.equals(this.actual, expected);\n});\n\nangular.scenario.matcher('toBe', function(expected) {\n  return this.actual === expected;\n});\n\nangular.scenario.matcher('toBeDefined', function() {\n  return angular.isDefined(this.actual);\n});\n\nangular.scenario.matcher('toBeTruthy', function() {\n  return this.actual;\n});\n\nangular.scenario.matcher('toBeFalsy', function() {\n  return !this.actual;\n});\n\nangular.scenario.matcher('toMatch', function(expected) {\n  return new RegExp(expected).test(this.actual);\n});\n\nangular.scenario.matcher('toBeNull', function() {\n  return this.actual === null;\n});\n\nangular.scenario.matcher('toContain', function(expected) {\n  return includes(this.actual, expected);\n});\n\nangular.scenario.matcher('toBeLessThan', function(expected) {\n  return this.actual < expected;\n});\n\nangular.scenario.matcher('toBeGreaterThan', function(expected) {\n  return this.actual > expected;\n});\n\n/**\n * User Interface for the Scenario Runner.\n *\n * TODO(esprehn): This should be refactored now that ObjectModel exists\n *  to use angular bindings for the UI.\n */\nangular.scenario.output('html', function(context, runner, model) {\n  var specUiMap = {},\n      lastStepUiMap = {};\n\n  context.append(\n    '<div id=\"header\">' +\n    '  <h1><span class=\"angular\">AngularJS</span>: Scenario Test Runner</h1>' +\n    '  <ul id=\"status-legend\" class=\"status-display\">' +\n    '    <li class=\"status-error\">0 Errors</li>' +\n    '    <li class=\"status-failure\">0 Failures</li>' +\n    '    <li class=\"status-success\">0 Passed</li>' +\n    '  </ul>' +\n    '</div>' +\n    '<div id=\"specs\">' +\n    '  <div class=\"test-children\"></div>' +\n    '</div>'\n  );\n\n  runner.on('InteractivePause', function(spec) {\n    var ui = lastStepUiMap[spec.id];\n    ui.find('.test-title').\n      html('paused... <a href=\"javascript:resume()\">resume</a> when ready.');\n  });\n\n  runner.on('SpecBegin', function(spec) {\n    var ui = findContext(spec);\n    ui.find('> .tests').append(\n      '<li class=\"status-pending test-it\"></li>'\n    );\n    ui = ui.find('> .tests li:last');\n    ui.append(\n      '<div class=\"test-info\">' +\n      '  <p class=\"test-title\">' +\n      '    <span class=\"timer-result\"></span>' +\n      '    <span class=\"test-name\"></span>' +\n      '  </p>' +\n      '</div>' +\n      '<div class=\"scrollpane\">' +\n      '  <ol class=\"test-actions\"></ol>' +\n      '</div>'\n    );\n    ui.find('> .test-info .test-name').text(spec.name);\n    ui.find('> .test-info').click(function() {\n      var scrollpane = ui.find('> .scrollpane');\n      var actions = scrollpane.find('> .test-actions');\n      var name = context.find('> .test-info .test-name');\n      if (actions.find(':visible').length) {\n        actions.hide();\n        name.removeClass('open').addClass('closed');\n      } else {\n        actions.show();\n        scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n        name.removeClass('closed').addClass('open');\n      }\n    });\n\n    specUiMap[spec.id] = ui;\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var ui = specUiMap[spec.id];\n    ui.append('<pre></pre>');\n    ui.find('> pre').text(formatException(error));\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    ui.removeClass('status-pending');\n    ui.addClass('status-' + spec.status);\n    ui.find(\"> .test-info .timer-result\").text(spec.duration + \"ms\");\n    if (spec.status === 'success') {\n      ui.find('> .test-info .test-name').addClass('closed');\n      ui.find('> .scrollpane .test-actions').hide();\n    }\n    updateTotals(spec.status);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    ui.find('> .scrollpane .test-actions').append('<li class=\"status-pending\"></li>');\n    var stepUi = lastStepUiMap[spec.id] = ui.find('> .scrollpane .test-actions li:last');\n    stepUi.append(\n      '<div class=\"timer-result\"></div>' +\n      '<div class=\"test-title\"></div>'\n    );\n    stepUi.find('> .test-title').text(step.name);\n    var scrollpane = stepUi.parents('.scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepEnd', function(spec, step) {\n    var stepUi = lastStepUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    stepUi.find('.timer-result').text(step.duration + 'ms');\n    stepUi.removeClass('status-pending');\n    stepUi.addClass('status-' + step.status);\n    var scrollpane = specUiMap[spec.id].find('> .scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  /**\n   * Finds the context of a spec block defined by the passed definition.\n   *\n   * @param {Object} The definition created by the Describe object.\n   */\n  function findContext(spec) {\n    var currentContext = context.find('#specs');\n    angular.forEach(model.getDefinitionPath(spec), function(defn) {\n      var id = 'describe-' + defn.id;\n      if (!context.find('#' + id).length) {\n        currentContext.find('> .test-children').append(\n          '<div class=\"test-describe\" id=\"' + id + '\">' +\n          '  <h2></h2>' +\n          '  <div class=\"test-children\"></div>' +\n          '  <ul class=\"tests\"></ul>' +\n          '</div>'\n        );\n        context.find('#' + id).find('> h2').text('describe: ' + defn.name);\n      }\n      currentContext = context.find('#' + id);\n    });\n    return context.find('#describe-' + spec.definition.id);\n  }\n\n  /**\n   * Updates the test counter for the status.\n   *\n   * @param {string} the status.\n   */\n  function updateTotals(status) {\n    var legend = context.find('#status-legend .status-' + status);\n    var parts = legend.text().split(' ');\n    var value = (parts[0] * 1) + 1;\n    legend.text(value + ' ' + parts[1]);\n  }\n\n  /**\n   * Add an error to a step.\n   *\n   * @param {Object} The JQuery wrapped context\n   * @param {function()} fn() that should return the file/line number of the error\n   * @param {Object} the error.\n   */\n  function addError(context, line, error) {\n    context.find('.test-title').append('<pre></pre>');\n    var message = _jQuery.trim(line() + '\\n\\n' + formatException(error));\n    context.find('.test-title pre:last').text(message);\n  }\n});\n\n/**\n * Generates JSON output into a context.\n */\nangular.scenario.output('json', function(context, runner, model) {\n  model.on('RunnerEnd', function() {\n    context.text(angular.toJson(model.value));\n  });\n});\n\n/**\n * Generates XML output into a context.\n */\nangular.scenario.output('xml', function(context, runner, model) {\n  var $ = function(args) {return new context.init(args);};\n  model.on('RunnerEnd', function() {\n    var scenario = $('<scenario></scenario>');\n    context.append(scenario);\n    serializeXml(scenario, model.value);\n  });\n\n  /**\n   * Convert the tree into XML.\n   *\n   * @param {Object} context jQuery context to add the XML to.\n   * @param {Object} tree node to serialize\n   */\n  function serializeXml(context, tree) {\n     angular.forEach(tree.children, function(child) {\n       var describeContext = $('<describe></describe>');\n       describeContext.attr('id', child.id);\n       describeContext.attr('name', child.name);\n       context.append(describeContext);\n       serializeXml(describeContext, child);\n     });\n     var its = $('<its></its>');\n     context.append(its);\n     angular.forEach(tree.specs, function(spec) {\n       var it = $('<it></it>');\n       it.attr('id', spec.id);\n       it.attr('name', spec.name);\n       it.attr('duration', spec.duration);\n       it.attr('status', spec.status);\n       its.append(it);\n       angular.forEach(spec.steps, function(step) {\n         var stepContext = $('<step></step>');\n         stepContext.attr('name', step.name);\n         stepContext.attr('duration', step.duration);\n         stepContext.attr('status', step.status);\n         it.append(stepContext);\n         if (step.error) {\n           var error = $('<error></error>');\n           stepContext.append(error);\n           error.text(formatException(stepContext.error));\n         }\n       });\n     });\n   }\n});\n\n/**\n * Creates a global value $result with the result of the runner.\n */\nangular.scenario.output('object', function(context, runner, model) {\n  runner.$window.$result = model.value;\n});\nbindJQuery();\npublishExternalAPI(angular);\n\nvar $runner = new angular.scenario.Runner(window),\n    scripts = document.getElementsByTagName('script'),\n    script = scripts[scripts.length - 1],\n    config = {};\n\nangular.forEach(script.attributes, function(attr) {\n  var match = attr.name.match(/ng[:\\-](.*)/);\n  if (match) {\n    config[match[1]] = attr.value || true;\n  }\n});\n\nif (config.autotest) {\n  JQLite(document).ready(function() {\n    angular.scenario.setUpAndRun(config);\n  });\n}\n})(window, document);\n\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n\\n[ng\\\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\\n.ng-cloak, .x-ng-cloak {\\n  display: none;\\n}\\n\\nng\\\\:form {\\n  display: block;\\n}\\n</style>');\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n/* CSS Document */\\n\\n/** Structure */\\nbody {\\n  font-family: Arial, sans-serif;\\n  margin: 0;\\n  font-size: 14px;\\n}\\n\\n#system-error {\\n  font-size: 1.5em;\\n  text-align: center;\\n}\\n\\n#json, #xml {\\n  display: none;\\n}\\n\\n#header {\\n  position: fixed;\\n  width: 100%;\\n}\\n\\n#specs {\\n  padding-top: 50px;\\n}\\n\\n#header .angular {\\n  font-family: Courier New, monospace;\\n  font-weight: bold;\\n}\\n\\n#header h1 {\\n  font-weight: normal;\\n  float: left;\\n  font-size: 30px;\\n  line-height: 30px;\\n  margin: 0;\\n  padding: 10px 10px;\\n  height: 30px;\\n}\\n\\n#application h2,\\n#specs h2 {\\n  margin: 0;\\n  padding: 0.5em;\\n  font-size: 1.1em;\\n}\\n\\n#status-legend {\\n  margin-top: 10px;\\n  margin-right: 10px;\\n}\\n\\n#header,\\n#application,\\n.test-info,\\n.test-actions li {\\n  overflow: hidden;\\n}\\n\\n#application {\\n  margin: 10px;\\n}\\n\\n#application iframe {\\n  width: 100%;\\n  height: 758px;\\n}\\n\\n#application .popout {\\n  float: right;\\n}\\n\\n#application iframe {\\n  border: none;\\n}\\n\\n.tests li,\\n.test-actions li,\\n.test-it li,\\n.test-it ol,\\n.status-display {\\n  list-style-type: none;\\n}\\n\\n.tests,\\n.test-it ol,\\n.status-display {\\n  margin: 0;\\n  padding: 0;\\n}\\n\\n.test-info {\\n  margin-left: 1em;\\n  margin-top: 0.5em;\\n  border-radius: 8px 0 0 8px;\\n  -webkit-border-radius: 8px 0 0 8px;\\n  -moz-border-radius: 8px 0 0 8px;\\n  cursor: pointer;\\n}\\n\\n.test-info:hover .test-name {\\n  text-decoration: underline;\\n}\\n\\n.test-info .closed:before {\\n  content: \\'\\\\25b8\\\\00A0\\';\\n}\\n\\n.test-info .open:before {\\n  content: \\'\\\\25be\\\\00A0\\';\\n  font-weight: bold;\\n}\\n\\n.test-it ol {\\n  margin-left: 2.5em;\\n}\\n\\n.status-display,\\n.status-display li {\\n  float: right;\\n}\\n\\n.status-display li {\\n  padding: 5px 10px;\\n}\\n\\n.timer-result,\\n.test-title {\\n  display: inline-block;\\n  margin: 0;\\n  padding: 4px;\\n}\\n\\n.test-actions .test-title,\\n.test-actions .test-result {\\n  display: table-cell;\\n  padding-left: 0.5em;\\n  padding-right: 0.5em;\\n}\\n\\n.test-actions {\\n  display: table;\\n}\\n\\n.test-actions li {\\n  display: table-row;\\n}\\n\\n.timer-result {\\n  width: 4em;\\n  padding: 0 10px;\\n  text-align: right;\\n  font-family: monospace;\\n}\\n\\n.test-it pre,\\n.test-actions pre {\\n  clear: left;\\n  color: black;\\n  margin-left: 6em;\\n}\\n\\n.test-describe {\\n  padding-bottom: 0.5em;\\n}\\n\\n.test-describe .test-describe {\\n  margin: 5px 5px 10px 2em;\\n}\\n\\n.test-actions .status-pending .test-title:before {\\n  content: \\'\\\\00bb\\\\00A0\\';\\n}\\n\\n.scrollpane {\\n   max-height: 20em;\\n   overflow: auto;\\n}\\n\\n/** Colors */\\n\\n#header {\\n  background-color: #F2C200;\\n}\\n\\n#specs h2 {\\n  border-top: 2px solid #BABAD1;\\n}\\n\\n#specs h2,\\n#application h2 {\\n  background-color: #efefef;\\n}\\n\\n#application {\\n  border: 1px solid #BABAD1;\\n}\\n\\n.test-describe .test-describe {\\n  border-left: 1px solid #BABAD1;\\n  border-right: 1px solid #BABAD1;\\n  border-bottom: 1px solid #BABAD1;\\n}\\n\\n.status-display {\\n  border: 1px solid #777;\\n}\\n\\n.status-display .status-pending,\\n.status-pending .test-info {\\n  background-color: #F9EEBC;\\n}\\n\\n.status-display .status-success,\\n.status-success .test-info {\\n  background-color: #B1D7A1;\\n}\\n\\n.status-display .status-failure,\\n.status-failure .test-info {\\n  background-color: #FF8286;\\n}\\n\\n.status-display .status-error,\\n.status-error .test-info {\\n  background-color: black;\\n  color: white;\\n}\\n\\n.test-actions .status-success .test-title {\\n  color: #30B30A;\\n}\\n\\n.test-actions .status-failure .test-title {\\n  color: #DF0000;\\n}\\n\\n.test-actions .status-error .test-title {\\n  color: black;\\n}\\n\\n.test-actions .timer-result {\\n  color: #888;\\n}\\n</style>');"
  },
  {
    "path": "chapter2/recipe7/test/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter2/recipe7/test/unit/controllersSpec.js",
    "content": "'use strict';\n\n/* jasmine specs for controllers go here */\n\ndescribe('MyCtrl', function(){\n  var scope, ctrl;\n\n  beforeEach(inject(function($injector, $controller, $rootScope) {  \n    scope = $rootScope.$new();\n    ctrl = $controller(MyCtrl, { $scope: scope });\n  }));\n\n  it('should change greeting value if name value is changed', function() {\n    scope.name = \"Frederik\";\n    scope.$digest();\n    expect(scope.greeting).toBe(\"Greetings Frederik\");\n  });\n});"
  },
  {
    "path": "chapter3/recipe1/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter3/recipe1/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app>\n    <label><input type=\"checkbox\" ng-model=\"checked\"/>Toggle Button</label>\n    <button ng-disabled=\"checked\">Press me</button>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter3/recipe1/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter3/recipe2/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter3/recipe2/index.html",
    "content": "<html>\n  <head>\n    <script src=\"http://code.jquery.com/jquery.min.js\"></script>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <my-widget>\n      <p>Hello World</p>\n    </my-widget>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter3/recipe2/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter3/recipe2/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.directive(\"myWidget\", function() {\n  var linkFunction = function(scope, element, attributes) {\n    var paragraph = element.children()[0];\n    $(paragraph).on(\"click\", function() {\n      $(this).css({ \"background-color\": \"red\" });\n    });\n  };\n\n  return {\n    restrict: \"E\",\n    link: linkFunction\n  };\n});"
  },
  {
    "path": "chapter3/recipe3/README.md",
    "content": "# angular-seed — the seed for AngularJS apps\n\nThis project is an application skeleton for a typical [AngularJS](http://angularjs.org/) web app.\nYou can use it to quickly bootstrap your angular webapp projects and dev environment for these\nprojects.\n\nThe seed contains AngularJS libraries, test libraries and a bunch of scripts all preconfigured for\ninstant web development gratification. Just clone the repo (or download the zip/tarball), start up\nour (or yours) webserver and you are ready to develop and test your application.\n\nThe seed app doesn't do much, just shows how to wire two controllers and views together. You can\ncheck it out by opening app/index.html in your browser (might not work file `file://` scheme in\ncertain browsers, see note below).\n\n_Note: While angular is client-side-only technology and it's possible to create angular webapps that\ndon't require a backend server at all, we recommend hosting the project files using a local\nwebserver during development to avoid issues with security restrictions (sandbox) in browsers. The\nsandbox implementation varies between browsers, but quite often prevents things like cookies, xhr,\netc to function properly when an html page is opened via `file://` scheme instead of `http://`._\n\n\n## How to use angular-seed\n\nClone the angular-seed repository and start hacking...\n\n\n### Running the app during development\n\nYou can pick one of these options:\n\n* serve this repository with your webserver\n* install node.js and run `scripts/web-server.js`\n\nThen navigate your browser to `http://localhost:<port>/app/index.html` to see the app running in\nyour browser.\n\n\n### Running the app in production\n\nThis really depends on how complex is your app and the overall infrastructure of your system, but\nthe general rule is that all you need in production are all the files under the `app/` directory.\nEverything else should be omitted.\n\nAngular apps are really just a bunch of static html, css and js files that just need to be hosted\nsomewhere, where they can be accessed by browsers.\n\nIf your Angular app is talking to the backend server via xhr or other means, you need to figure\nout what is the best way to host the static files to comply with the same origin policy if\napplicable. Usually this is done by hosting the files by the backend server or through\nreverse-proxying the backend server(s) and a webserver(s).\n\n\n### Running unit tests\n\nWe recommend using [jasmine](http://pivotal.github.com/jasmine/) and\n[Testacular](http://vojtajina.github.com/testacular/) for your unit tests/specs, but you are free\nto use whatever works for you.\n\nRequires [node.js](http://nodejs.org/), Testacular (`sudo npm install -g testacular`) and a local\nor remote browser.\n\n* start `scripts/test.sh` (on windows: `scripts\\test.bat`)\n  * a browser will start and connect to the Testacular server (Chrome is default browser, others can be captured by loading the same url as the one in Chrome or by changing the `config/testacular.conf.js` file)\n* to run or re-run tests just change any of your source or test javascript files\n\n\n### End to end testing\n\nAngular ships with a baked-in end-to-end test runner that understands angular, your app and allows\nyou to write your tests with jasmine-like BDD syntax.\n\nRequires a webserver, node.js + `./scripts/web-server.js` or your backend server that hosts the angular static files.\n\nCheck out the\n[end-to-end runner's documentation](http://docs.angularjs.org/guide/dev_guide.e2e-testing) for more\ninfo.\n\n* create your end-to-end tests in `test/e2e/scenarios.js`\n* serve your project directory with your http/backend server or node.js + `scripts/web-server.js`\n* to run do one of:\n  * open `http://localhost:port/test/e2e/runner.html` in your browser\n  * run the tests from console with [Testacular](vojtajina.github.com/testacular) via\n    `scripts/e2e-test.sh` or `script/e2e-test.bat`\n\n\n### Receiving updates from upstream\n\nWhen we upgrade angular-seed's repo with newer angular or testing library code, you can just\nfetch the changes and merge them into your project with git.\n\n\n## Directory Layout\n\n    app/                --> all of the files to be used in production\n      css/              --> css files\n        app.css         --> default stylesheet\n      img/              --> image files\n      index.html        --> app layout file (the main html template file of the app)\n      index-async.html  --> just like index.html, but loads js files asynchronously\n      js/               --> javascript files\n        app.js          --> application\n        controllers.js  --> application controllers\n        directives.js   --> application directives\n        filters.js      --> custom angular filters\n        services.js     --> custom angular services\n      lib/              --> angular and 3rd party javascript libraries\n        angular/\n          angular.js        --> the latest angular js\n          angular.min.js    --> the latest minified angular js\n          angular-*.js      --> angular add-on modules\n          version.txt       --> version number\n      partials/             --> angular view partials (partial html templates)\n        partial1.html\n        partial2.html\n\n    config/testacular.conf.js        --> config file for running unit tests with Testacular\n    config/testacular-e2e.conf.js    --> config file for running e2e tests with Testacular\n\n    scripts/            --> handy shell/js/ruby scripts\n      e2e-test.sh       --> runs end-to-end tests with Testacular (*nix)\n      e2e-test.bat      --> runs end-to-end tests with Testacular (windows)\n      test.bat          --> autotests unit tests with Testacular (windows)\n      test.sh           --> autotests unit tests with Testacular (*nix)\n      web-server.js     --> simple development webserver based on node.js\n\n    test/               --> test source files and libraries\n      e2e/              -->\n        runner.html     --> end-to-end test runner (open in your browser to run)\n        scenarios.js    --> end-to-end specs\n      lib/\n        angular/                --> angular testing libraries\n          angular-mocks.js      --> mocks that replace certain angular services in tests\n          angular-scenario.js   --> angular's scenario (end-to-end) test runner library\n          version.txt           --> version file\n      unit/                     --> unit level specs/tests\n        controllersSpec.js      --> specs for controllers\n        directivessSpec.js      --> specs for directives\n        filtersSpec.js          --> specs for filters\n        servicesSpec.js         --> specs for services\n\n## Contact\n\nFor more information on AngularJS please check out http://angularjs.org/\n"
  },
  {
    "path": "chapter3/recipe3/app/css/.gitignore",
    "content": ""
  },
  {
    "path": "chapter3/recipe3/app/css/app.css",
    "content": "/* app css stylesheet */\n\n.menu {\n  list-style: none;\n  border-bottom: 0.1em solid black;\n  margin-bottom: 2em;\n  padding: 0 0 0.5em;\n}\n\n.menu:before {\n  content: \"[\";\n}\n\n.menu:after {\n  content: \"]\";\n}\n\n.menu > li {\n  display: inline;\n}\n\n.menu > li:before {\n  content: \"|\";\n  padding-right: 0.3em;\n}\n\n.menu > li:nth-child(1):before {\n  content: \"\";\n  padding: 0;\n}\n"
  },
  {
    "path": "chapter3/recipe3/app/img/.gitignore",
    "content": ""
  },
  {
    "path": "chapter3/recipe3/app/index-async.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <style>\n    [ng-cloak] {\n      display: none;\n    }\n  </style>\n  <script>\n    // include angular loader, which allows the files to load in any order\n    /*\n     AngularJS v1.0.0rc1\n     (c) 2010-2012 AngularJS http://angularjs.org\n     License: MIT\n    */\n    'use strict';(function(i){function d(c,a,e){return c[a]||(c[a]=e())}return d(d(i,\"angular\",Object),\"module\",function(){var c={};return function(a,e,f){e&&c.hasOwnProperty(a)&&(c[a]=null);return d(c,a,function(){function b(a,b,d){return function(){c[d||\"push\"]([a,b,arguments]);return g}}if(!e)throw Error(\"No module: \"+a);var c=[],d=[],h=b(\"$injector\",\"invoke\"),g={_invokeQueue:c,_runBlocks:d,requires:e,name:a,provider:b(\"$provide\",\"provider\"),factory:b(\"$provide\",\"factory\"),service:b(\"$provide\",\"service\"),\n    value:b(\"$provide\",\"value\"),constant:b(\"$provide\",\"constant\",\"unshift\"),filter:b(\"$filterProvider\",\"register\"),directive:b(\"$compileProvider\",\"directive\"),config:h,run:function(a){d.push(a);return this}};f&&h(f);return g})}})})(window);\n\n    // include a third-party async loader library\n    /*!\n     * $script.js v1.3\n     * https://github.com/ded/script.js\n     * Copyright: @ded & @fat - Dustin Diaz, Jacob Thornton 2011\n     * Follow our software http://twitter.com/dedfat\n     * License: MIT\n     */\n    !function(a,b,c){function t(a,c){var e=b.createElement(\"script\"),f=j;e.onload=e.onerror=e[o]=function(){e[m]&&!/^c|loade/.test(e[m])||f||(e.onload=e[o]=null,f=1,c())},e.async=1,e.src=a,d.insertBefore(e,d.firstChild)}function q(a,b){p(a,function(a){return!b(a)})}var d=b.getElementsByTagName(\"head\")[0],e={},f={},g={},h={},i=\"string\",j=!1,k=\"push\",l=\"DOMContentLoaded\",m=\"readyState\",n=\"addEventListener\",o=\"onreadystatechange\",p=function(a,b){for(var c=0,d=a.length;c<d;++c)if(!b(a[c]))return j;return 1};!b[m]&&b[n]&&(b[n](l,function r(){b.removeEventListener(l,r,j),b[m]=\"complete\"},j),b[m]=\"loading\");var s=function(a,b,d){function o(){if(!--m){e[l]=1,j&&j();for(var a in g)p(a.split(\"|\"),n)&&!q(g[a],n)&&(g[a]=[])}}function n(a){return a.call?a():e[a]}a=a[k]?a:[a];var i=b&&b.call,j=i?b:d,l=i?a.join(\"\"):b,m=a.length;c(function(){q(a,function(a){h[a]?(l&&(f[l]=1),o()):(h[a]=1,l&&(f[l]=1),t(s.path?s.path+a+\".js\":a,o))})},0);return s};s.get=t,s.ready=function(a,b,c){a=a[k]?a:[a];var d=[];!q(a,function(a){e[a]||d[k](a)})&&p(a,function(a){return e[a]})?b():!function(a){g[a]=g[a]||[],g[a][k](b),c&&c(d)}(a.join(\"|\"));return s};var u=a.$script;s.noConflict=function(){a.$script=u;return this},typeof module!=\"undefined\"&&module.exports?module.exports=s:a.$script=s}(this,document,setTimeout)\n\n    // load all of the dependencies asynchronously.\n    $script([\n      'lib/angular/angular.js',\n      'js/app.js',\n      'js/services.js',\n      'js/controllers.js',\n      'js/filters.js',\n      'js/directives.js'\n    ], function() {\n      // when all is done, execute bootstrap angular application\n      angular.bootstrap(document, ['myApp']);\n    });\n  </script>\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\">\n</head>\n<body ng-cloak>\n  <ul class=\"menu\">\n    <li><a href=\"#/view1\">view1</a></li>\n    <li><a href=\"#/view2\">view2</a></li>\n  </ul>\n\n  <div ng-view></div>\n\n  <div>Angular seed app: v<span app-version></span></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "chapter3/recipe3/app/index.html",
    "content": "<!doctype html>\n<html lang=\"en\" ng-app=\"MyApp\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\"/>\n</head>\n<body>\n  <my-widget></my-widget>\n  <my-widget-replace></my-widget-replace>\n  <my-widget-template></my-widget-template>\n\n\n  <script src=\"lib/angular/angular.js\"></script>\n  <script src=\"js/app.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "chapter3/recipe3/app/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.directive(\"myWidget\", function() {\n  return {\n    restrict: \"E\",\n    template: \"<p>Hello World</p>\"\n  };\n});\n\napp.directive(\"myWidgetReplace\", function() {\n  return {\n    restrict: \"E\",\n    replace: true,\n    template: \"<p>Hello World</p>\"\n  };\n});\n\napp.directive(\"myWidgetTemplate\", function() {\n  return {\n    restrict: \"E\",\n    replace: true,\n    templateUrl: \"widget.html\"\n  };\n});"
  },
  {
    "path": "chapter3/recipe3/app/lib/angular/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngCookies\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookies\n   * @requires $browser\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from\n   * this object, new cookies are created/deleted at the end of current $eval.\n   *\n   * @example\n   */\n   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for(name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            if (angular.isDefined(lastCookies[name])) {\n              cookies[name] = lastCookies[name];\n            } else {\n              delete cookies[name];\n            }\n          } else if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated){\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   * @example\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#get\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          return angular.fromJson($cookies[key]);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#put\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#remove\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter3/recipe3/app/lib/angular/angular-loader.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n\n(\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n'use strict';\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n)(window);\n\n/**\n * Closure compiler type information\n *\n * @typedef { {\n *   requires: !Array.<string>,\n *   invokeQueue: !Array.<Array.<*>>,\n *\n *   service: function(string, Function):angular.Module,\n *   factory: function(string, Function):angular.Module,\n *   value: function(string, *):angular.Module,\n *\n *   filter: function(string, Function):angular.Module,\n *\n *   init: function(Function):angular.Module\n * } }\n */\nangular.Module;\n\n"
  },
  {
    "path": "chapter3/recipe3/app/lib/angular/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g. \n *   `http://example.com:8080/api`), you'll need to escape the colon character before the port\n *   number, like this: `$resource('http://example.com\\\\:8080/api')`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` – {string} – The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` – {object=} – Optional set of pre-bound parameters for this action.\n *   - isArray – {boolean=} – If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n     * encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace((pctEncodeSpaces ? null : /%20/g), '+');\n    }\n\n    function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        action.method = angular.uppercase(action.method);\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter3/recipe3/app/lib/angular/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             '<p style=\"color:blue\">an html\\n' +\n             '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n             'snippet</p>';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n          Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n           <table>\n             <tr>\n               <td>Filter</td>\n               <td>Source</td>\n               <td>Rendered</td>\n             </tr>\n             <tr id=\"html-filter\">\n               <td>html filter</td>\n               <td>\n                 <pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre>\n               </td>\n               <td>\n                 <div ng-bind-html=\"snippet\"></div>\n               </td>\n             </tr>\n             <tr id=\"escaped-html\">\n               <td>no filter</td>\n               <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind=\"snippet\"></div></td>\n             </tr>\n             <tr id=\"html-unsafe-filter\">\n               <td>unsafe html filter</td>\n               <td><pre>&lt;div ng-bind-html-unsafe=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind-html-unsafe=\"snippet\"></div></td>\n             </tr>\n           </table>\n         </div>\n     </doc:source>\n     <doc:scenario>\n       it('should sanitize the html snippet ', function() {\n         expect(using('#html-filter').element('div').html()).\n           toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n       });\n\n       it('should escape snippet without any filter', function() {\n         expect(using('#escaped-html').element('div').html()).\n           toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n                \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n                \"snippet&lt;/p&gt;\");\n       });\n\n       it('should inline raw snippet if filtered as unsafe', function() {\n         expect(using('#html-unsafe-filter').element(\"div\").html()).\n           toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n                \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n                \"snippet</p>\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new <b>text</b>');\n         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');\n         expect(using('#escaped-html').element('div').html()).toBe(\"new &lt;b&gt;text&lt;/b&gt;\");\n         expect(using('#html-unsafe-filter').binding(\"snippet\")).toBe('new <b>text</b>');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar $sanitize = function(html) {\n  var buf = [];\n    htmlParser(html, htmlSanitizeWriter(buf));\n    return buf.join('');\n};\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP = /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  URI_REGEXP = /^((ftp|https?):\\/\\/|mailto:|#)/,\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g; // Match everything outside of normal chars and \" (quote character)\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,aside,\" +\n        \"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,\" +\n        \"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,bdi,bdo,\" +\n        \"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,\" +\n        \"span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        index = html.indexOf(\"-->\");\n\n        if ( index >= 0 ) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'), function(all, text){\n        text = text.\n          replace(COMMENT_REGEXP, \"$1\").\n          replace(CDATA_REGEXP, \"$1\");\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n\n        return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw \"Parse Error: \" + html;\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {\n      var value = doubleQuotedValue\n        || singleQoutedValue\n        || unqoutedValue\n        || '';\n\n      attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nvar hiddenPre=document.createElement(\"pre\");\nfunction decodeEntities(value) {\n  hiddenPre.innerHTML=value.replace(/</g,\"&lt;\");\n  return hiddenPre.innerText || hiddenPre.textContent || '';\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] == true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] == true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).value('$sanitize', $sanitize);\n\n/**\n * @ngdoc directive\n * @name ngSanitize.directive:ngBindHtml\n *\n * @description\n * Creates a binding that will sanitize the result of evaluating the `expression` with the\n * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n */\nangular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);\n    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {\n      value = $sanitize(value);\n      element.html(value || '');\n    });\n  };\n}]);\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n *   plain email address links.\n *\n * @param {string} text Input text.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should linkify the snippet with urls', function() {\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('Pretty text with some links:&#10;' +\n                '<a href=\"http://angularjs.org/\">http://angularjs.org/</a>,&#10;' +\n                '<a href=\"mailto:us@somewhere.org\">us@somewhere.org</a>,&#10;' +\n                '<a href=\"mailto:another@somewhere.org\">another@somewhere.org</a>,&#10;' +\n                'and one more: <a href=\"ftp://127.0.0.1/\">ftp://127.0.0.1/</a>.');\n       });\n\n       it ('should not linkify snippet without the linky filter', function() {\n         expect(using('#escaped-html').binding('snippet')).\n           toBe(\"Pretty text with some links:\\n\" +\n                \"http://angularjs.org/,\\n\" +\n                \"mailto:us@somewhere.org,\\n\" +\n                \"another@somewhere.org,\\n\" +\n                \"and one more: ftp://127.0.0.1/.\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new http://link.');\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('new <a href=\"http://link\">http://link</a>.');\n         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', function() {\n  var LINKY_URL_REGEXP = /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s\\.\\;\\,\\(\\)\\{\\}\\<\\>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    // TODO(vojta): use $sanitize instead\n    var writer = htmlSanitizeWriter(html);\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      writer.chars(raw.substr(0, i));\n      writer.start('a', {href:url});\n      writer.chars(match[0].replace(MAILTO_REGEXP, ''));\n      writer.end('a');\n      raw = raw.substring(i + match[0].length);\n    }\n    writer.chars(raw);\n    return html.join('');\n  };\n});\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter3/recipe3/app/lib/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter3/recipe3/app/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter3/recipe3/app/partials/.gitignore",
    "content": ""
  },
  {
    "path": "chapter3/recipe3/app/partials/partial1.html",
    "content": "<p>This is the partial for view 1.</p>\n"
  },
  {
    "path": "chapter3/recipe3/app/partials/partial2.html",
    "content": "<p>This is the partial for view 2.</p>\n<p>\n  Showing of 'interpolate' filter:\n  {{ 'Current version is v%VERSION%.' | interpolate }}\n</p>\n"
  },
  {
    "path": "chapter3/recipe3/app/widget.html",
    "content": "<p>This is the external template!</p>"
  },
  {
    "path": "chapter3/recipe3/config/testacular-e2e.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  ANGULAR_SCENARIO,\n  ANGULAR_SCENARIO_ADAPTER,\n  'test/e2e/**/*.js'\n];\n\nautoWatch = false;\n\nbrowsers = ['Chrome'];\n\nsingleRun = true;\n\nproxies = {\n  '/': 'http://localhost:8000/'\n};\n\njunitReporter = {\n  outputFile: 'test_out/e2e.xml',\n  suite: 'e2e'\n};\n"
  },
  {
    "path": "chapter3/recipe3/config/testacular.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  JASMINE,\n  JASMINE_ADAPTER,\n  'app/lib/angular/angular.js',\n  'app/lib/angular/angular-*.js',\n  'test/lib/angular/angular-mocks.js',\n  'app/js/**/*.js',\n  'test/unit/**/*.js'\n];\n\nautoWatch = true;\n\nbrowsers = ['Chrome'];\n\njunitReporter = {\n  outputFile: 'test_out/unit.xml',\n  suite: 'unit'\n};\n"
  },
  {
    "path": "chapter3/recipe3/logs/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "chapter3/recipe3/scripts/e2e-test.bat",
    "content": "@echo off\n\nREM Windows script for running e2e tests\nREM You have to run server and capture some browser first\nREM\nREM Requirements:\nREM - NodeJS (http://nodejs.org/)\nREM - Testacular (npm install -g testacular)\n\nset BASE_DIR=%~dp0\ntestacular start \"%BASE_DIR%\\..\\config\\testacular-e2e.conf.js\" %*\n"
  },
  {
    "path": "chapter3/recipe3/scripts/e2e-test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular-e2e.conf.js $*\n"
  },
  {
    "path": "chapter3/recipe3/scripts/test.bat",
    "content": "@echo off\r\n\r\nREM Windows script for running unit tests\r\nREM You have to run server and capture some browser first\r\nREM\r\nREM Requirements:\r\nREM - NodeJS (http://nodejs.org/)\r\nREM - Testacular (npm install -g testacular)\r\n\r\nset BASE_DIR=%~dp0\r\ntestacular start \"%BASE_DIR%\\..\\config\\testacular.conf.js\" %*\r\n"
  },
  {
    "path": "chapter3/recipe3/scripts/test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular.conf.js $*\n"
  },
  {
    "path": "chapter3/recipe3/scripts/watchr.rb",
    "content": "#!/usr/bin/env watchr\n\n# config file for watchr http://github.com/mynyml/watchr\n# install: gem install watchr\n# run: watch watchr.rb\n# note: make sure that you have jstd server running (server.sh) and a browser captured\n\nlog_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log')\n\n`cd ..`\n`touch #{log_file}`\n\nputs \"String watchr... log file: #{log_file}\"\n\nwatch( '(app/js|test/unit)' )  do\n  `echo \"\\n\\ntest run started @ \\`date\\`\" > #{log_file}`\n  `scripts/test.sh &> #{log_file}`\nend\n\n"
  },
  {
    "path": "chapter3/recipe3/scripts/web-server.js",
    "content": "#!/usr/bin/env node\n\nvar util = require('util'),\n    http = require('http'),\n    fs = require('fs'),\n    url = require('url'),\n    events = require('events');\n\nvar DEFAULT_PORT = 8000;\n\nfunction main(argv) {\n  new HttpServer({\n    'GET': createServlet(StaticServlet),\n    'HEAD': createServlet(StaticServlet)\n  }).start(Number(argv[2]) || DEFAULT_PORT);\n}\n\nfunction escapeHtml(value) {\n  return value.toString().\n    replace('<', '&lt;').\n    replace('>', '&gt;').\n    replace('\"', '&quot;');\n}\n\nfunction createServlet(Class) {\n  var servlet = new Class();\n  return servlet.handleRequest.bind(servlet);\n}\n\n/**\n * An Http server implementation that uses a map of methods to decide\n * action routing.\n *\n * @param {Object} Map of method => Handler function\n */\nfunction HttpServer(handlers) {\n  this.handlers = handlers;\n  this.server = http.createServer(this.handleRequest_.bind(this));\n}\n\nHttpServer.prototype.start = function(port) {\n  this.port = port;\n  this.server.listen(port);\n  util.puts('Http Server running at http://localhost:' + port + '/');\n};\n\nHttpServer.prototype.parseUrl_ = function(urlString) {\n  var parsed = url.parse(urlString);\n  parsed.pathname = url.resolve('/', parsed.pathname);\n  return url.parse(url.format(parsed), true);\n};\n\nHttpServer.prototype.handleRequest_ = function(req, res) {\n  var logEntry = req.method + ' ' + req.url;\n  if (req.headers['user-agent']) {\n    logEntry += ' ' + req.headers['user-agent'];\n  }\n  util.puts(logEntry);\n  req.url = this.parseUrl_(req.url);\n  var handler = this.handlers[req.method];\n  if (!handler) {\n    res.writeHead(501);\n    res.end();\n  } else {\n    handler.call(this, req, res);\n  }\n};\n\n/**\n * Handles static content.\n */\nfunction StaticServlet() {}\n\nStaticServlet.MimeMap = {\n  'txt': 'text/plain',\n  'html': 'text/html',\n  'css': 'text/css',\n  'xml': 'application/xml',\n  'json': 'application/json',\n  'js': 'application/javascript',\n  'jpg': 'image/jpeg',\n  'jpeg': 'image/jpeg',\n  'gif': 'image/gif',\n  'png': 'image/png',\n  'svg': 'image/svg+xml'\n};\n\nStaticServlet.prototype.handleRequest = function(req, res) {\n  var self = this;\n  var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){\n    return String.fromCharCode(parseInt(hex, 16));\n  });\n  var parts = path.split('/');\n  if (parts[parts.length-1].charAt(0) === '.')\n    return self.sendForbidden_(req, res, path);\n  fs.stat(path, function(err, stat) {\n    if (err)\n      return self.sendMissing_(req, res, path);\n    if (stat.isDirectory())\n      return self.sendDirectory_(req, res, path);\n    return self.sendFile_(req, res, path);\n  });\n}\n\nStaticServlet.prototype.sendError_ = function(req, res, error) {\n  res.writeHead(500, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>Internal Server Error</title>\\n');\n  res.write('<h1>Internal Server Error</h1>');\n  res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');\n  util.puts('500 Internal Server Error');\n  util.puts(util.inspect(error));\n};\n\nStaticServlet.prototype.sendMissing_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(404, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>404 Not Found</title>\\n');\n  res.write('<h1>Not Found</h1>');\n  res.write(\n    '<p>The requested URL ' +\n    escapeHtml(path) +\n    ' was not found on this server.</p>'\n  );\n  res.end();\n  util.puts('404 Not Found: ' + path);\n};\n\nStaticServlet.prototype.sendForbidden_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(403, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>403 Forbidden</title>\\n');\n  res.write('<h1>Forbidden</h1>');\n  res.write(\n    '<p>You do not have permission to access ' +\n    escapeHtml(path) + ' on this server.</p>'\n  );\n  res.end();\n  util.puts('403 Forbidden: ' + path);\n};\n\nStaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {\n  res.writeHead(301, {\n      'Content-Type': 'text/html',\n      'Location': redirectUrl\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>301 Moved Permanently</title>\\n');\n  res.write('<h1>Moved Permanently</h1>');\n  res.write(\n    '<p>The document has moved <a href=\"' +\n    redirectUrl +\n    '\">here</a>.</p>'\n  );\n  res.end();\n  util.puts('301 Moved Permanently: ' + redirectUrl);\n};\n\nStaticServlet.prototype.sendFile_ = function(req, res, path) {\n  var self = this;\n  var file = fs.createReadStream(path);\n  res.writeHead(200, {\n    'Content-Type': StaticServlet.\n      MimeMap[path.split('.').pop()] || 'text/plain'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n  } else {\n    file.on('data', res.write.bind(res));\n    file.on('close', function() {\n      res.end();\n    });\n    file.on('error', function(error) {\n      self.sendError_(req, res, error);\n    });\n  }\n};\n\nStaticServlet.prototype.sendDirectory_ = function(req, res, path) {\n  var self = this;\n  if (path.match(/[^\\/]$/)) {\n    req.url.pathname += '/';\n    var redirectUrl = url.format(url.parse(url.format(req.url)));\n    return self.sendRedirect_(req, res, redirectUrl);\n  }\n  fs.readdir(path, function(err, files) {\n    if (err)\n      return self.sendError_(req, res, error);\n\n    if (!files.length)\n      return self.writeDirectoryIndex_(req, res, path, []);\n\n    var remaining = files.length;\n    files.forEach(function(fileName, index) {\n      fs.stat(path + '/' + fileName, function(err, stat) {\n        if (err)\n          return self.sendError_(req, res, err);\n        if (stat.isDirectory()) {\n          files[index] = fileName + '/';\n        }\n        if (!(--remaining))\n          return self.writeDirectoryIndex_(req, res, path, files);\n      });\n    });\n  });\n};\n\nStaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {\n  path = path.substring(1);\n  res.writeHead(200, {\n    'Content-Type': 'text/html'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n    return;\n  }\n  res.write('<!doctype html>\\n');\n  res.write('<title>' + escapeHtml(path) + '</title>\\n');\n  res.write('<style>\\n');\n  res.write('  ol { list-style-type: none; font-size: 1.2em; }\\n');\n  res.write('</style>\\n');\n  res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');\n  res.write('<ol>');\n  files.forEach(function(fileName) {\n    if (fileName.charAt(0) !== '.') {\n      res.write('<li><a href=\"' +\n        escapeHtml(fileName) + '\">' +\n        escapeHtml(fileName) + '</a></li>');\n    }\n  });\n  res.write('</ol>');\n  res.end();\n};\n\n// Must be last,\nmain(process.argv);\n"
  },
  {
    "path": "chapter3/recipe3/test/e2e/runner.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <title>End2end Test Runner</title>\n    <script src=\"../lib/angular/angular-scenario.js\" ng-autotest></script>\n    <script src=\"scenarios.js\"></script>\n  </head>\n  <body>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter3/recipe3/test/e2e/scenarios.js",
    "content": "'use strict';\n\n/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */\n\ndescribe('my app', function() {\n\n  beforeEach(function() {\n    browser().navigateTo('../../app/index.html');\n  });\n\n\n  it('should automatically redirect to /view1 when location hash/fragment is empty', function() {\n    expect(browser().location().url()).toBe(\"/view1\");\n  });\n\n\n  describe('view1', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view1');\n    });\n\n\n    it('should render view1 when user navigates to /view1', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 1/);\n    });\n\n  });\n\n\n  describe('view2', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view2');\n    });\n\n\n    it('should render view2 when user navigates to /view2', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 2/);\n    });\n\n  });\n});\n"
  },
  {
    "path": "chapter3/recipe3/test/lib/angular/angular-mocks.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n *\n * TODO(vojta): wrap whole file into closure during build\n */\n\n/**\n * @ngdoc overview\n * @name angular.mock\n * @description\n *\n * Namespace from 'angular-mocks.js' which contains testing related code.\n */\nangular.mock = {};\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ngMock.$browser\n *\n * @description\n * This service is a mock implementation of {@link ng.$browser}. It provides fake\n * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,\n * cookies, etc...\n *\n * The api of this service is the same as that of the real {@link ng.$browser $browser}, except\n * that there are several helper methods available which can be used in tests.\n */\nangular.mock.$BrowserProvider = function() {\n  this.$get = function(){\n    return new angular.mock.$Browser();\n  };\n};\n\nangular.mock.$Browser = function() {\n  var self = this;\n\n  this.isMock = true;\n  self.$$url = \"http://server/\";\n  self.$$lastUrl = self.$$url; // used by url polling fn\n  self.pollFns = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = angular.noop;\n  self.$$incOutstandingRequestCount = angular.noop;\n\n\n  // register url polling fn\n\n  self.onUrlChange = function(listener) {\n    self.pollFns.push(\n      function() {\n        if (self.$$lastUrl != self.$$url) {\n          self.$$lastUrl = self.$$url;\n          listener(self.$$url);\n        }\n      }\n    );\n\n    return listener;\n  };\n\n  self.cookieHash = {};\n  self.lastCookieHash = {};\n  self.deferredFns = [];\n  self.deferredNextId = 0;\n\n  self.defer = function(fn, delay) {\n    delay = delay || 0;\n    self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});\n    self.deferredFns.sort(function(a,b){ return a.time - b.time;});\n    return self.deferredNextId++;\n  };\n\n\n  self.defer.now = 0;\n\n\n  self.defer.cancel = function(deferId) {\n    var fnIndex;\n\n    angular.forEach(self.deferredFns, function(fn, index) {\n      if (fn.id === deferId) fnIndex = index;\n    });\n\n    if (fnIndex !== undefined) {\n      self.deferredFns.splice(fnIndex, 1);\n      return true;\n    }\n\n    return false;\n  };\n\n\n  /**\n   * @name ngMock.$browser#defer.flush\n   * @methodOf ngMock.$browser\n   *\n   * @description\n   * Flushes all pending requests and executes the defer callbacks.\n   *\n   * @param {number=} number of milliseconds to flush. See {@link #defer.now}\n   */\n  self.defer.flush = function(delay) {\n    if (angular.isDefined(delay)) {\n      self.defer.now += delay;\n    } else {\n      if (self.deferredFns.length) {\n        self.defer.now = self.deferredFns[self.deferredFns.length-1].time;\n      } else {\n        throw Error('No deferred tasks to be flushed');\n      }\n    }\n\n    while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {\n      self.deferredFns.shift().fn();\n    }\n  };\n  /**\n   * @name ngMock.$browser#defer.now\n   * @propertyOf ngMock.$browser\n   *\n   * @description\n   * Current milliseconds mock time.\n   */\n\n  self.$$baseHref = '';\n  self.baseHref = function() {\n    return this.$$baseHref;\n  };\n};\nangular.mock.$Browser.prototype = {\n\n/**\n  * @name ngMock.$browser#poll\n  * @methodOf ngMock.$browser\n  *\n  * @description\n  * run all fns in pollFns\n  */\n  poll: function poll() {\n    angular.forEach(this.pollFns, function(pollFn){\n      pollFn();\n    });\n  },\n\n  addPollFn: function(pollFn) {\n    this.pollFns.push(pollFn);\n    return pollFn;\n  },\n\n  url: function(url, replace) {\n    if (url) {\n      this.$$url = url;\n      return this;\n    }\n\n    return this.$$url;\n  },\n\n  cookies:  function(name, value) {\n    if (name) {\n      if (value == undefined) {\n        delete this.cookieHash[name];\n      } else {\n        if (angular.isString(value) &&       //strings only\n            value.length <= 4096) {          //strict cookie storage limits\n          this.cookieHash[name] = value;\n        }\n      }\n    } else {\n      if (!angular.equals(this.cookieHash, this.lastCookieHash)) {\n        this.lastCookieHash = angular.copy(this.cookieHash);\n        this.cookieHash = angular.copy(this.cookieHash);\n      }\n      return this.cookieHash;\n    }\n  },\n\n  notifyWhenNoOutstandingRequests: function(fn) {\n    fn();\n  }\n};\n\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandlerProvider\n *\n * @description\n * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed\n * into the `$exceptionHandler`.\n */\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandler\n *\n * @description\n * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed\n * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration\n * information.\n *\n *\n * <pre>\n *   describe('$exceptionHandlerProvider', function() {\n *\n *     it('should capture log messages and exceptions', function() {\n *\n *       module(function($exceptionHandlerProvider) {\n *         $exceptionHandlerProvider.mode('log');\n *       });\n *\n *       inject(function($log, $exceptionHandler, $timeout) {\n *         $timeout(function() { $log.log(1); });\n *         $timeout(function() { $log.log(2); throw 'banana peel'; });\n *         $timeout(function() { $log.log(3); });\n *         expect($exceptionHandler.errors).toEqual([]);\n *         expect($log.assertEmpty());\n *         $timeout.flush();\n *         expect($exceptionHandler.errors).toEqual(['banana peel']);\n *         expect($log.log.logs).toEqual([[1], [2], [3]]);\n *       });\n *     });\n *   });\n * </pre>\n */\n\nangular.mock.$ExceptionHandlerProvider = function() {\n  var handler;\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$exceptionHandlerProvider#mode\n   * @methodOf ngMock.$exceptionHandlerProvider\n   *\n   * @description\n   * Sets the logging mode.\n   *\n   * @param {string} mode Mode of operation, defaults to `rethrow`.\n   *\n   *   - `rethrow`: If any errors are are passed into the handler in tests, it typically\n   *                means that there is a bug in the application or test, so this mock will\n   *                make these tests fail.\n   *   - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores an\n   *            array of errors in `$exceptionHandler.errors`, to allow later assertion of them.\n   *            See {@link ngMock.$log#assertEmpty assertEmpty()} and\n   *             {@link ngMock.$log#reset reset()}\n   */\n  this.mode = function(mode) {\n    switch(mode) {\n      case 'rethrow':\n        handler = function(e) {\n          throw e;\n        };\n        break;\n      case 'log':\n        var errors = [];\n\n        handler = function(e) {\n          if (arguments.length == 1) {\n            errors.push(e);\n          } else {\n            errors.push([].slice.call(arguments, 0));\n          }\n        };\n\n        handler.errors = errors;\n        break;\n      default:\n        throw Error(\"Unknown mode '\" + mode + \"', only 'log'/'rethrow' modes are allowed!\");\n    }\n  };\n\n  this.$get = function() {\n    return handler;\n  };\n\n  this.mode('rethrow');\n};\n\n\n/**\n * @ngdoc service\n * @name ngMock.$log\n *\n * @description\n * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays\n * (one array per logging level). These arrays are exposed as `logs` property of each of the\n * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.\n *\n */\nangular.mock.$LogProvider = function() {\n\n  function concat(array1, array2, index) {\n    return array1.concat(Array.prototype.slice.call(array2, index));\n  }\n\n\n  this.$get = function () {\n    var $log = {\n      log: function() { $log.log.logs.push(concat([], arguments, 0)); },\n      warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },\n      info: function() { $log.info.logs.push(concat([], arguments, 0)); },\n      error: function() { $log.error.logs.push(concat([], arguments, 0)); }\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#reset\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Reset all of the logging arrays to empty.\n     */\n    $log.reset = function () {\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#log.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.log.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#warn.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.warn.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#info.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.info.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#error.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.error.logs = [];\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#assertEmpty\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.\n     */\n    $log.assertEmpty = function() {\n      var errors = [];\n      angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {\n        angular.forEach($log[logLevel].logs, function(log) {\n          angular.forEach(log, function (logItem) {\n            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\\n' + (logItem.stack || ''));\n          });\n        });\n      });\n      if (errors.length) {\n        errors.unshift(\"Expected $log to be empty! Either a message was logged unexpectedly, or an expected \" +\n          \"log message was not checked and removed:\");\n        errors.push('');\n        throw new Error(errors.join('\\n---------\\n'));\n      }\n    };\n\n    $log.reset();\n    return $log;\n  };\n};\n\n\n(function() {\n  var R_ISO8061_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?:\\:?(\\d\\d)(?:\\:?(\\d\\d)(?:\\.(\\d{3}))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d)))?$/;\n\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8061_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n  function int(str) {\n    return parseInt(str, 10);\n  }\n\n  function padNumber(num, digits, trim) {\n    var neg = '';\n    if (num < 0) {\n      neg =  '-';\n      num = -num;\n    }\n    num = '' + num;\n    while(num.length < digits) num = '0' + num;\n    if (trim)\n      num = num.substr(num.length - digits);\n    return neg + num;\n  }\n\n\n  /**\n   * @ngdoc object\n   * @name angular.mock.TzDate\n   * @description\n   *\n   * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.\n   *\n   * Mock of the Date type which has its timezone specified via constroctor arg.\n   *\n   * The main purpose is to create Date-like instances with timezone fixed to the specified timezone\n   * offset, so that we can test code that depends on local timezone settings without dependency on\n   * the time zone settings of the machine where the code is running.\n   *\n   * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)\n   * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*\n   *\n   * @example\n   * !!!! WARNING !!!!!\n   * This is not a complete Date object so only methods that were implemented can be called safely.\n   * To make matters worse, TzDate instances inherit stuff from Date via a prototype.\n   *\n   * We do our best to intercept calls to \"unimplemented\" methods, but since the list of methods is\n   * incomplete we might be missing some non-standard methods. This can result in errors like:\n   * \"Date.prototype.foo called on incompatible Object\".\n   *\n   * <pre>\n   * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');\n   * newYearInBratislava.getTimezoneOffset() => -60;\n   * newYearInBratislava.getFullYear() => 2010;\n   * newYearInBratislava.getMonth() => 0;\n   * newYearInBratislava.getDate() => 1;\n   * newYearInBratislava.getHours() => 0;\n   * newYearInBratislava.getMinutes() => 0;\n   * </pre>\n   *\n   */\n  angular.mock.TzDate = function (offset, timestamp) {\n    var self = new Date(0);\n    if (angular.isString(timestamp)) {\n      var tsStr = timestamp;\n\n      self.origDate = jsonStringToDate(timestamp);\n\n      timestamp = self.origDate.getTime();\n      if (isNaN(timestamp))\n        throw {\n          name: \"Illegal Argument\",\n          message: \"Arg '\" + tsStr + \"' passed into TzDate constructor is not a valid date string\"\n        };\n    } else {\n      self.origDate = new Date(timestamp);\n    }\n\n    var localOffset = new Date(timestamp).getTimezoneOffset();\n    self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;\n    self.date = new Date(timestamp + self.offsetDiff);\n\n    self.getTime = function() {\n      return self.date.getTime() - self.offsetDiff;\n    };\n\n    self.toLocaleDateString = function() {\n      return self.date.toLocaleDateString();\n    };\n\n    self.getFullYear = function() {\n      return self.date.getFullYear();\n    };\n\n    self.getMonth = function() {\n      return self.date.getMonth();\n    };\n\n    self.getDate = function() {\n      return self.date.getDate();\n    };\n\n    self.getHours = function() {\n      return self.date.getHours();\n    };\n\n    self.getMinutes = function() {\n      return self.date.getMinutes();\n    };\n\n    self.getSeconds = function() {\n      return self.date.getSeconds();\n    };\n\n    self.getTimezoneOffset = function() {\n      return offset * 60;\n    };\n\n    self.getUTCFullYear = function() {\n      return self.origDate.getUTCFullYear();\n    };\n\n    self.getUTCMonth = function() {\n      return self.origDate.getUTCMonth();\n    };\n\n    self.getUTCDate = function() {\n      return self.origDate.getUTCDate();\n    };\n\n    self.getUTCHours = function() {\n      return self.origDate.getUTCHours();\n    };\n\n    self.getUTCMinutes = function() {\n      return self.origDate.getUTCMinutes();\n    };\n\n    self.getUTCSeconds = function() {\n      return self.origDate.getUTCSeconds();\n    };\n\n    self.getUTCMilliseconds = function() {\n      return self.origDate.getUTCMilliseconds();\n    };\n\n    self.getDay = function() {\n      return self.date.getDay();\n    };\n\n    // provide this method only on browsers that already have it\n    if (self.toISOString) {\n      self.toISOString = function() {\n        return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +\n              padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +\n              padNumber(self.origDate.getUTCDate(), 2) + 'T' +\n              padNumber(self.origDate.getUTCHours(), 2) + ':' +\n              padNumber(self.origDate.getUTCMinutes(), 2) + ':' +\n              padNumber(self.origDate.getUTCSeconds(), 2) + '.' +\n              padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'\n      }\n    }\n\n    //hide all methods not implemented in this mock that the Date prototype exposes\n    var unimplementedMethods = ['getMilliseconds', 'getUTCDay',\n        'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',\n        'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',\n        'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',\n        'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',\n        'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];\n\n    angular.forEach(unimplementedMethods, function(methodName) {\n      self[methodName] = function() {\n        throw Error(\"Method '\" + methodName + \"' is not implemented in the TzDate mock\");\n      };\n    });\n\n    return self;\n  };\n\n  //make \"tzDateInstance instanceof Date\" return true\n  angular.mock.TzDate.prototype = Date.prototype;\n})();\n\n\n/**\n * @ngdoc function\n * @name angular.mock.dump\n * @description\n *\n * *NOTE*: this is not an injectable instance, just a globally available function.\n *\n * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.\n *\n * This method is also available on window, where it can be used to display objects on debug console.\n *\n * @param {*} object - any object to turn into string.\n * @return {string} a serialized string of the argument\n */\nangular.mock.dump = function(object) {\n  return serialize(object);\n\n  function serialize(object) {\n    var out;\n\n    if (angular.isElement(object)) {\n      object = angular.element(object);\n      out = angular.element('<div></div>');\n      angular.forEach(object, function(element) {\n        out.append(angular.element(element).clone());\n      });\n      out = out.html();\n    } else if (angular.isArray(object)) {\n      out = [];\n      angular.forEach(object, function(o) {\n        out.push(serialize(o));\n      });\n      out = '[ ' + out.join(', ') + ' ]';\n    } else if (angular.isObject(object)) {\n      if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {\n        out = serializeScope(object);\n      } else if (object instanceof Error) {\n        out = object.stack || ('' + object.name + ': ' + object.message);\n      } else {\n        out = angular.toJson(object, true);\n      }\n    } else {\n      out = String(object);\n    }\n\n    return out;\n  }\n\n  function serializeScope(scope, offset) {\n    offset = offset ||  '  ';\n    var log = [offset + 'Scope(' + scope.$id + '): {'];\n    for ( var key in scope ) {\n      if (scope.hasOwnProperty(key) && !key.match(/^(\\$|this)/)) {\n        log.push('  ' + key + ': ' + angular.toJson(scope[key]));\n      }\n    }\n    var child = scope.$$childHead;\n    while(child) {\n      log.push(serializeScope(child, offset + '  '));\n      child = child.$$nextSibling;\n    }\n    log.push('}');\n    return log.join('\\n' + offset);\n  }\n};\n\n/**\n * @ngdoc object\n * @name ngMock.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for unit testing application that use the\n * {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less\n * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.\n *\n * During unit testing, we want our unit tests to run quickly and have no external dependencies so\n * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or\n * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is\n * to verify whether a certain request has been sent or not, or alternatively just let the\n * application make requests, respond with pre-trained responses and assert that the end result is\n * what we expect it to be.\n *\n * This mock implementation can be used to respond with static or dynamic responses via the\n * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).\n *\n * When an Angular application needs some data from a server, it calls the $http service, which\n * sends the request to a real server using $httpBackend service. With dependency injection, it is\n * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify\n * the requests and respond with some testing data without sending a request to real server.\n *\n * There are two ways to specify what test data should be returned as http responses by the mock\n * backend when the code under test makes http requests:\n *\n * - `$httpBackend.expect` - specifies a request expectation\n * - `$httpBackend.when` - specifies a backend definition\n *\n *\n * # Request Expectations vs Backend Definitions\n *\n * Request expectations provide a way to make assertions about requests made by the application and\n * to define responses for those requests. The test will fail if the expected requests are not made\n * or they are made in the wrong order.\n *\n * Backend definitions allow you to define a fake backend for your application which doesn't assert\n * if a particular request was made or not, it just returns a trained response if a request is made.\n * The test will pass whether or not the request gets made during testing.\n *\n *\n * <table class=\"table\">\n *   <tr><th width=\"220px\"></th><th>Request expectations</th><th>Backend definitions</th></tr>\n *   <tr>\n *     <th>Syntax</th>\n *     <td>.expect(...).respond(...)</td>\n *     <td>.when(...).respond(...)</td>\n *   </tr>\n *   <tr>\n *     <th>Typical usage</th>\n *     <td>strict unit tests</td>\n *     <td>loose (black-box) unit testing</td>\n *   </tr>\n *   <tr>\n *     <th>Fulfills multiple requests</th>\n *     <td>NO</td>\n *     <td>YES</td>\n *   </tr>\n *   <tr>\n *     <th>Order of requests matters</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Request required</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Response required</th>\n *     <td>optional (see below)</td>\n *     <td>YES</td>\n *   </tr>\n * </table>\n *\n * In cases where both backend definitions and request expectations are specified during unit\n * testing, the request expectations are evaluated first.\n *\n * If a request expectation has no response specified, the algorithm will search your backend\n * definitions for an appropriate response.\n *\n * If a request didn't match any expectation or if the expectation doesn't have the response\n * defined, the backend definitions are evaluated in sequential order to see if any of them match\n * the request. The response from the first matched definition is returned.\n *\n *\n * # Flushing HTTP requests\n *\n * The $httpBackend used in production, always responds to requests with responses asynchronously.\n * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are\n * hard to write, follow and maintain. At the same time the testing mock, can't respond\n * synchronously because that would change the execution of the code under test. For this reason the\n * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending\n * requests and thus preserving the async api of the backend, while allowing the test to execute\n * synchronously.\n *\n *\n * # Unit testing with mock $httpBackend\n *\n * <pre>\n   // controller\n   function MyController($scope, $http) {\n     $http.get('/auth.py').success(function(data) {\n       $scope.user = data;\n     });\n\n     this.saveMessage = function(message) {\n       $scope.status = 'Saving...';\n       $http.post('/add-msg.py', message).success(function(response) {\n         $scope.status = '';\n       }).error(function() {\n         $scope.status = 'ERROR!';\n       });\n     };\n   }\n\n   // testing controller\n   var $httpBackend;\n\n   beforeEach(inject(function($injector) {\n     $httpBackend = $injector.get('$httpBackend');\n\n     // backend definition common for all tests\n     $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});\n   }));\n\n\n   afterEach(function() {\n     $httpBackend.verifyNoOutstandingExpectation();\n     $httpBackend.verifyNoOutstandingRequest();\n   });\n\n\n   it('should fetch authentication token', function() {\n     $httpBackend.expectGET('/auth.py');\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n   });\n\n\n   it('should send msg to server', function() {\n     // now you don’t care about the authentication, but\n     // the controller will still send the request and\n     // $httpBackend will respond without you having to\n     // specify the expectation and response for this request\n     $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');\n\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n     controller.saveMessage('message content');\n     expect(controller.status).toBe('Saving...');\n     $httpBackend.flush();\n     expect(controller.status).toBe('');\n   });\n\n\n   it('should send auth header', function() {\n     $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {\n       // check if the header was send, if it wasn't the expectation won't\n       // match the request and the test will fail\n       return headers['Authorization'] == 'xxx';\n     }).respond(201, '');\n\n     var controller = scope.$new(MyController);\n     controller.saveMessage('whatever');\n     $httpBackend.flush();\n   });\n   </pre>\n */\nangular.mock.$HttpBackendProvider = function() {\n  this.$get = [createHttpBackendMock];\n};\n\n/**\n * General factory function for $httpBackend mock.\n * Returns instance for unit testing (when no arguments specified):\n *   - passing through is disabled\n *   - auto flushing is disabled\n *\n * Returns instance for e2e testing (when `$delegate` and `$browser` specified):\n *   - passing through (delegating request to real backend) is enabled\n *   - auto flushing is enabled\n *\n * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)\n * @param {Object=} $browser Auto-flushing enabled if specified\n * @return {Object} Instance of $httpBackend mock\n */\nfunction createHttpBackendMock($delegate, $browser) {\n  var definitions = [],\n      expectations = [],\n      responses = [],\n      responsesPush = angular.bind(responses, responses.push);\n\n  function createResponse(status, data, headers) {\n    if (angular.isFunction(status)) return status;\n\n    return function() {\n      return angular.isNumber(status)\n          ? [status, data, headers]\n          : [200, status, data];\n    };\n  }\n\n  // TODO(vojta): change params to: method, url, data, headers, callback\n  function $httpBackend(method, url, data, callback, headers) {\n    var xhr = new MockXhr(),\n        expectation = expectations[0],\n        wasExpected = false;\n\n    function prettyPrint(data) {\n      return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)\n          ? data\n          : angular.toJson(data);\n    }\n\n    if (expectation && expectation.match(method, url)) {\n      if (!expectation.matchData(data))\n        throw Error('Expected ' + expectation + ' with different data\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.data) + '\\nGOT:      ' + data);\n\n      if (!expectation.matchHeaders(headers))\n        throw Error('Expected ' + expectation + ' with different headers\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.headers) + '\\nGOT:      ' +\n            prettyPrint(headers));\n\n      expectations.shift();\n\n      if (expectation.response) {\n        responses.push(function() {\n          var response = expectation.response(method, url, data, headers);\n          xhr.$$respHeaders = response[2];\n          callback(response[0], response[1], xhr.getAllResponseHeaders());\n        });\n        return;\n      }\n      wasExpected = true;\n    }\n\n    var i = -1, definition;\n    while ((definition = definitions[++i])) {\n      if (definition.match(method, url, data, headers || {})) {\n        if (definition.response) {\n          // if $browser specified, we do auto flush all requests\n          ($browser ? $browser.defer : responsesPush)(function() {\n            var response = definition.response(method, url, data, headers);\n            xhr.$$respHeaders = response[2];\n            callback(response[0], response[1], xhr.getAllResponseHeaders());\n          });\n        } else if (definition.passThrough) {\n          $delegate(method, url, data, callback, headers);\n        } else throw Error('No response defined !');\n        return;\n      }\n    }\n    throw wasExpected ?\n        Error('No response defined !') :\n        Error('Unexpected request: ' + method + ' ' + url + '\\n' +\n              (expectation ? 'Expected ' + expectation : 'No more request expected'));\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#when\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current definition.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.when = function(method, url, data, headers) {\n    var definition = new MockHttpExpectation(method, url, data, headers),\n        chain = {\n          respond: function(status, data, headers) {\n            definition.response = createResponse(status, data, headers);\n          }\n        };\n\n    if ($browser) {\n      chain.passThrough = function() {\n        definition.passThrough = true;\n      };\n    }\n\n    definitions.push(definition);\n    return chain;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for GET requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for HEAD requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for DELETE requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for POST requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for PUT requests.  For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for JSONP requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n  createShortMethods('when');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expect\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current expectation.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *  request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.expect = function(method, url, data, headers) {\n    var expectation = new MockHttpExpectation(method, url, data, headers);\n    expectations.push(expectation);\n    return {\n      respond: function(status, data, headers) {\n        expectation.response = createResponse(status, data, headers);\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for GET requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled. See #expect for more info.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for HEAD requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for DELETE requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for POST requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PUT requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPATCH\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PATCH requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for JSONP requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n  createShortMethods('expect');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#flush\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Flushes all pending requests using the trained responses.\n   *\n   * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,\n   *   all pending requests will be flushed. If there are no pending requests when the flush method\n   *   is called an exception is thrown (as this typically a sign of programming error).\n   */\n  $httpBackend.flush = function(count) {\n    if (!responses.length) throw Error('No pending request to flush !');\n\n    if (angular.isDefined(count)) {\n      while (count--) {\n        if (!responses.length) throw Error('No more pending request to flush !');\n        responses.shift()();\n      }\n    } else {\n      while (responses.length) {\n        responses.shift()();\n      }\n    }\n    $httpBackend.verifyNoOutstandingExpectation();\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingExpectation\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that all of the requests defined via the `expect` api were made. If any of the\n   * requests were not made, verifyNoOutstandingExpectation throws an exception.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyExpectations);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingExpectation = function() {\n    if (expectations.length) {\n      throw Error('Unsatisfied requests: ' + expectations.join(', '));\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingRequest\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that there are no outstanding requests that need to be flushed.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyNoOutstandingRequest);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingRequest = function() {\n    if (responses.length) {\n      throw Error('Unflushed requests: ' + responses.length);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#resetExpectations\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Resets all request expectations, but preserves all backend definitions. Typically, you would\n   * call resetExpectations during a multiple-phase test when you want to reuse the same instance of\n   * $httpBackend mock.\n   */\n  $httpBackend.resetExpectations = function() {\n    expectations.length = 0;\n    responses.length = 0;\n  };\n\n  return $httpBackend;\n\n\n  function createShortMethods(prefix) {\n    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {\n     $httpBackend[prefix + method] = function(url, headers) {\n       return $httpBackend[prefix](method, url, undefined, headers)\n     }\n    });\n\n    angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {\n      $httpBackend[prefix + method] = function(url, data, headers) {\n        return $httpBackend[prefix](method, url, data, headers)\n      }\n    });\n  }\n}\n\nfunction MockHttpExpectation(method, url, data, headers) {\n\n  this.data = data;\n  this.headers = headers;\n\n  this.match = function(m, u, d, h) {\n    if (method != m) return false;\n    if (!this.matchUrl(u)) return false;\n    if (angular.isDefined(d) && !this.matchData(d)) return false;\n    if (angular.isDefined(h) && !this.matchHeaders(h)) return false;\n    return true;\n  };\n\n  this.matchUrl = function(u) {\n    if (!url) return true;\n    if (angular.isFunction(url.test)) return url.test(u);\n    return url == u;\n  };\n\n  this.matchHeaders = function(h) {\n    if (angular.isUndefined(headers)) return true;\n    if (angular.isFunction(headers)) return headers(h);\n    return angular.equals(headers, h);\n  };\n\n  this.matchData = function(d) {\n    if (angular.isUndefined(data)) return true;\n    if (data && angular.isFunction(data.test)) return data.test(d);\n    if (data && !angular.isString(data)) return angular.toJson(data) == d;\n    return data == d;\n  };\n\n  this.toString = function() {\n    return method + ' ' + url;\n  };\n}\n\nfunction MockXhr() {\n\n  // hack for testing $http, $httpBackend\n  MockXhr.$$lastInstance = this;\n\n  this.open = function(method, url, async) {\n    this.$$method = method;\n    this.$$url = url;\n    this.$$async = async;\n    this.$$reqHeaders = {};\n    this.$$respHeaders = {};\n  };\n\n  this.send = function(data) {\n    this.$$data = data;\n  };\n\n  this.setRequestHeader = function(key, value) {\n    this.$$reqHeaders[key] = value;\n  };\n\n  this.getResponseHeader = function(name) {\n    // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last\n    var header = this.$$respHeaders[name];\n    if (header) return header;\n\n    name = angular.lowercase(name);\n    header = this.$$respHeaders[name];\n    if (header) return header;\n\n    header = undefined;\n    angular.forEach(this.$$respHeaders, function(headerVal, headerName) {\n      if (!header && angular.lowercase(headerName) == name) header = headerVal;\n    });\n    return header;\n  };\n\n  this.getAllResponseHeaders = function() {\n    var lines = [];\n\n    angular.forEach(this.$$respHeaders, function(value, key) {\n      lines.push(key + ': ' + value);\n    });\n    return lines.join('\\n');\n  };\n\n  this.abort = angular.noop;\n}\n\n\n/**\n * @ngdoc function\n * @name ngMock.$timeout\n * @description\n *\n * This service is just a simple decorator for {@link ng.$timeout $timeout} service\n * that adds a \"flush\" method.\n */\n\n/**\n * @ngdoc method\n * @name ngMock.$timeout#flush\n * @methodOf ngMock.$timeout\n * @description\n *\n * Flushes the queue of pending tasks.\n */\n\n/**\n *\n */\nangular.mock.$RootElementProvider = function() {\n  this.$get = function() {\n    return angular.element('<div ng-app></div>');\n  }\n};\n\n/**\n * @ngdoc overview\n * @name ngMock\n * @description\n *\n * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful\n * mocks to the {@link AUTO.$injector $injector}.\n */\nangular.module('ngMock', ['ng']).provider({\n  $browser: angular.mock.$BrowserProvider,\n  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,\n  $log: angular.mock.$LogProvider,\n  $httpBackend: angular.mock.$HttpBackendProvider,\n  $rootElement: angular.mock.$RootElementProvider\n}).config(function($provide) {\n  $provide.decorator('$timeout', function($delegate, $browser) {\n    $delegate.flush = function() {\n      $browser.defer.flush();\n    };\n    return $delegate;\n  });\n});\n\n\n/**\n * @ngdoc overview\n * @name ngMockE2E\n * @description\n *\n * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.\n * Currently there is only one mock present in this module -\n * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.\n */\nangular.module('ngMockE2E', ['ng']).config(function($provide) {\n  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);\n});\n\n/**\n * @ngdoc object\n * @name ngMockE2E.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of\n * applications that use the {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for unit testing please see\n * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.\n *\n * This implementation can be used to respond with static or dynamic responses via the `when` api\n * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the\n * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch\n * templates from a webserver).\n *\n * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application\n * is being developed with the real backend api replaced with a mock, it is often desirable for\n * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch\n * templates or static files from the webserver). To configure the backend with this behavior\n * use the `passThrough` request handler of `when` instead of `respond`.\n *\n * Additionally, we don't want to manually have to flush mocked out requests like we do during unit\n * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests\n * automatically, closely simulating the behavior of the XMLHttpRequest object.\n *\n * To setup the application to run with this http backend, you have to create a module that depends\n * on the `ngMockE2E` and your application modules and defines the fake backend:\n *\n * <pre>\n *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);\n *   myAppDev.run(function($httpBackend) {\n *     phones = [{name: 'phone1'}, {name: 'phone2'}];\n *\n *     // returns the current list of phones\n *     $httpBackend.whenGET('/phones').respond(phones);\n *\n *     // adds a new phone to the phones array\n *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {\n *       phones.push(angular.fromJSON(data));\n *     });\n *     $httpBackend.whenGET(/^\\/templates\\//).passThrough();\n *     //...\n *   });\n * </pre>\n *\n * Afterwards, bootstrap your app with this new module.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#when\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition.\n *\n * @param {string} method HTTP method.\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n *   object and returns true if the headers match the current definition.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n *\n *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n *    – The respond method takes a set of static data to be returned or a function that can return\n *    an array containing response status (number), response data (string) and response headers\n *    (Object).\n *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`\n *    handler, will be pass through to the real backend (an XHR request will be made to the\n *    server.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenGET\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for GET requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenHEAD\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for HEAD requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenDELETE\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for DELETE requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPOST\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for POST requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPUT\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PUT requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPATCH\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PATCH requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenJSONP\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for JSONP requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\nangular.mock.e2e = {};\nangular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];\n\n\nangular.mock.clearDataCache = function() {\n  var key,\n      cache = angular.element.cache;\n\n  for(key in cache) {\n    if (cache.hasOwnProperty(key)) {\n      var handle = cache[key].handle;\n\n      handle && angular.element(handle.elem).unbind();\n      delete cache[key];\n    }\n  }\n};\n\n\nwindow.jstestdriver && (function(window) {\n  /**\n   * Global method to output any number of objects into JSTD console. Useful for debugging.\n   */\n  window.dump = function() {\n    var args = [];\n    angular.forEach(arguments, function(arg) {\n      args.push(angular.mock.dump(arg));\n    });\n    jstestdriver.console.log.apply(jstestdriver.console, args);\n    if (window.console) {\n      window.console.log.apply(window.console, args);\n    }\n  };\n})(window);\n\n\nwindow.jasmine && (function(window) {\n\n  afterEach(function() {\n    var spec = getCurrentSpec();\n    var injector = spec.$injector;\n\n    spec.$injector = null;\n    spec.$modules = null;\n\n    if (injector) {\n      injector.get('$rootElement').unbind();\n      injector.get('$browser').pollFns.length = 0;\n    }\n\n    angular.mock.clearDataCache();\n\n    // clean up jquery's fragment cache\n    angular.forEach(angular.element.fragments, function(val, key) {\n      delete angular.element.fragments[key];\n    });\n\n    MockXhr.$$lastInstance = null;\n\n    angular.forEach(angular.callbacks, function(val, key) {\n      delete angular.callbacks[key];\n    });\n    angular.callbacks.counter = 0;\n  });\n\n  function getCurrentSpec() {\n    return jasmine.getEnv().currentSpec;\n  }\n\n  function isSpecRunning() {\n    var spec = getCurrentSpec();\n    return spec && spec.queue.running;\n  }\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.module\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * This function registers a module configuration code. It collects the configuration information\n   * which will be used when the injector is created by {@link angular.mock.inject inject}.\n   *\n   * See {@link angular.mock.inject inject} for usage example\n   *\n   * @param {...(string|Function)} fns any number of modules which are represented as string\n   *        aliases or as anonymous module initialization functions. The modules are used to\n   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.\n   */\n  window.module = angular.mock.module = function() {\n    var moduleFns = Array.prototype.slice.call(arguments, 0);\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      if (spec.$injector) {\n        throw Error('Injector already created, can not register a module!');\n      } else {\n        var modules = spec.$modules || (spec.$modules = []);\n        angular.forEach(moduleFns, function(module) {\n          modules.push(module);\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.inject\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * The inject function wraps a function into an injectable function. The inject() creates new\n   * instance of {@link AUTO.$injector $injector} per test, which is then used for\n   * resolving references.\n   *\n   * See also {@link angular.mock.module module}\n   *\n   * Example of what a typical jasmine tests looks like with the inject method.\n   * <pre>\n   *\n   *   angular.module('myApplicationModule', [])\n   *       .value('mode', 'app')\n   *       .value('version', 'v1.0.1');\n   *\n   *\n   *   describe('MyApp', function() {\n   *\n   *     // You need to load modules that you want to test,\n   *     // it loads only the \"ng\" module by default.\n   *     beforeEach(module('myApplicationModule'));\n   *\n   *\n   *     // inject() is used to inject arguments of all given functions\n   *     it('should provide a version', inject(function(mode, version) {\n   *       expect(version).toEqual('v1.0.1');\n   *       expect(mode).toEqual('app');\n   *     }));\n   *\n   *\n   *     // The inject and module method can also be used inside of the it or beforeEach\n   *     it('should override a version and test the new version is injected', function() {\n   *       // module() takes functions or strings (module aliases)\n   *       module(function($provide) {\n   *         $provide.value('version', 'overridden'); // override version here\n   *       });\n   *\n   *       inject(function(version) {\n   *         expect(version).toEqual('overridden');\n   *       });\n   *     ));\n   *   });\n   *\n   * </pre>\n   *\n   * @param {...Function} fns any number of functions which will be injected using the injector.\n   */\n  window.inject = angular.mock.inject = function() {\n    var blockFns = Array.prototype.slice.call(arguments, 0);\n    var errorForStack = new Error('Declaration Location');\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      var modules = spec.$modules || [];\n      modules.unshift('ngMock');\n      modules.unshift('ng');\n      var injector = spec.$injector;\n      if (!injector) {\n        injector = spec.$injector = angular.injector(modules);\n      }\n      for(var i = 0, ii = blockFns.length; i < ii; i++) {\n        try {\n          injector.invoke(blockFns[i] || angular.noop, this);\n        } catch (e) {\n          if(e.stack) e.stack +=  '\\n' + errorForStack.stack;\n          throw e;\n        } finally {\n          errorForStack = null;\n        }\n      }\n    }\n  };\n})(window);\n"
  },
  {
    "path": "chapter3/recipe3/test/lib/angular/angular-scenario.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Mar 21 12:46:34 2012 -0700\n */\n(function( window, undefined ) {\n'use strict';\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.7.2\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in array && array[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n\t\tvar exec,\n\t\t\tbulk = key == null,\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\n\t\t// Sets many values\n\t\tif ( key && typeof key === \"object\" ) {\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n\t\t\t}\n\t\t\tchainable = 1;\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = pass === undefined && jQuery.isFunction( value );\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations only iterate when executing function values\n\t\t\t\tif ( exec ) {\n\t\t\t\t\texec = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn exec.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\n\t\t\t\t// Otherwise they run against the entire set\n\t\t\t\t} else {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor (; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchainable = 1;\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfired = true;\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar length = list.length;\n\t\t\t\t\tadd( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory || memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tfragment,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tpixelMargin: true\n\t};\n\n\t// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead\n\tjQuery.boxModel = support.boxModel = (document.compatMode === \"CSS1Compat\");\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor ( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\tfragment.removeChild( div );\n\n\t// Null elements to avoid leaks in IE\n\tfragment = select = opt = div = input = null;\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tmarginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,\n\t\t\tpaddingMarginBorderVisibility, paddingMarginBorder,\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tconMarginTop = 1;\n\t\tpaddingMarginBorder = \"padding:0;margin:0;border:\";\n\t\tpositionTopLeftWidthHeight = \"position:absolute;top:0;left:0;width:1px;height:1px;\";\n\t\tpaddingMarginBorderVisibility = paddingMarginBorder + \"0;visibility:hidden;\";\n\t\tstyle = \"style='\" + positionTopLeftWidthHeight + paddingMarginBorder + \"5px solid #000;\";\n\t\thtml = \"<div \" + style + \"display:block;'><div style='\" + paddingMarginBorder + \"0;display:block;overflow:hidden;'></div></div>\" +\n\t\t\t\"<table \" + style + \"' cellpadding='0' cellspacing='0'>\" +\n\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = paddingMarginBorderVisibility + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td style='\" + paddingMarginBorder + \"0;display:none'></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName( \"td\" );\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t// gets computed margin-right based on width of container. For more\n\t\t// info see bug #3333\n\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tmarginDiv = document.createElement( \"div\" );\n\t\t\tmarginDiv.style.width = \"0\";\n\t\t\tmarginDiv.style.marginRight = \"0\";\n\t\t\tdiv.style.width = \"2px\";\n\t\t\tdiv.appendChild( marginDiv );\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\t// (IE < 8 does this)\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.width = div.style.padding = \"1px\";\n\t\t\tdiv.style.border = 0;\n\t\t\tdiv.style.overflow = \"hidden\";\n\t\t\tdiv.style.display = \"inline\";\n\t\t\tdiv.style.zoom = 1;\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.style.overflow = \"visible\";\n\t\t\tdiv.innerHTML = \"<div style='width:5px;'></div>\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\t\t}\n\n\t\tdiv.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;\n\t\tdiv.innerHTML = html;\n\n\t\touter = div.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.style.marginTop = \"1%\";\n\t\t\tsupport.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== \"1%\";\n\t\t}\n\n\t\tif ( typeof container.style.zoom !== \"undefined\" ) {\n\t\t\tcontainer.style.zoom = 1;\n\t\t}\n\n\t\tbody.removeChild( container );\n\t\tmarginDiv = div = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\treturn support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ internalKey ] : internalKey;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ internalKey ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( internalKey );\n\t\t\t} else {\n\t\t\t\telem[ internalKey ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, part, attr, name, l,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = elem.attributes;\n\t\t\t\t\tfor ( l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split( \".\", 2 );\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\t\tpart = parts[1] + \"!\";\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\tdata = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\tif ( data === undefined && elem ) {\n\t\t\t\t\tdata = jQuery.data( elem, key );\n\t\t\t\t\tdata = dataAttr( elem, key, data );\n\t\t\t\t}\n\n\t\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\t\tdata;\n\t\t\t}\n\n\t\t\tparts[1] = value;\n\t\t\tthis.each(function() {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.triggerHandler( \"setData\" + part, parts );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + part, parts );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, false );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\thooks = {};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( object );\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, l, isBool,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\t\t\tattrNames = value.toLowerCase().split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tisBool = rboolean.test( name );\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\t// Do not do this for boolean attributes (see #10870)\n\t\t\t\t\tif ( !isBool ) {\n\t\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\t}\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( isBool && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true,\n\t\tcoords: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = \"\" + value );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+)?\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\tvar attrs = elem.attributes || {};\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || (attrs.id || {}).value === m[2]) &&\n\t\t\t(!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tquick: selector && quickParse( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t ( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\told = null;\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\tspecial = jQuery.event.special[ event.type ] || {},\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n\t\t\t// Pregenerate a single jQuery object for reuse with .is()\n\t\t\tjqcur = jQuery(this);\n\t\t\tjqcur.context = this.ownerDocument || this;\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process events on disabled elements (#6911, #8165)\n\t\t\t\tif ( cur.disabled !== true ) {\n\t\t\t\t\tselMatch = {};\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tjqcur[0] = cur;\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\t\tselMatch[ sel ] = (\n\t\t\t\t\t\t\t\thandleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\tret;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\t\t\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\telem._change_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) { // && selector != null\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( var type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\n\t\t\tparts.push( m[1] );\n\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\t\t/* falls through */\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n// Expose origPOS\n// \"global\" as in regardless of relation to brackets/parens\nExpr.match.globalPOS = origPOS;\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry {\n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.globalPOS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\tPOS.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery.clean(arguments) );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tnull;\n\t\t\t}\n\n\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, function( i, elem ) {\n\t\t\t\t\tif ( elem.src ) {\n\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\turl: elem.src,\n\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\tdataType: \"script\"\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\n\t// IE blanks contents when cloning scripts\n\t} else if ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdest.text = src.text;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n\n\t// Clear flags for bubbling special change/submit events, they must\n\t// be reattached when the newly cloned events are first activated\n\tdest.removeAttribute( \"_submit_attached\" );\n\tdest.removeAttribute( \"_change_attached\" );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n\t// Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n\tvar div = document.createElement( \"div\" );\n\tsafeFragment.appendChild( div );\n\n\tdiv.innerHTML = elem.outerHTML;\n\treturn div.firstChild;\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t\tclone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ?\n\t\t\t\telem.cloneNode( true ) :\n\t\t\t\tshimCloneNode( elem );\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType, script, j,\n\t\t\t\tret = [];\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\"),\n\t\t\t\t\t\tsafeChildNodes = safeFragment.childNodes,\n\t\t\t\t\t\tremove;\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\n\t\t\t\t\t// Clear elements from DocumentFragment (safeFragment or otherwise)\n\t\t\t\t\t// to avoid hoarding elements. Fixes #11356\n\t\t\t\t\tif ( div ) {\n\t\t\t\t\t\tdiv.parentNode.removeChild( div );\n\n\t\t\t\t\t\t// Guard against -1 index exceptions in FF3.6\n\t\t\t\t\t\tif ( safeChildNodes.length > 0 ) {\n\t\t\t\t\t\t\tremove = safeChildNodes[ safeChildNodes.length - 1 ];\n\n\t\t\t\t\t\t\tif ( remove && remove.parentNode ) {\n\t\t\t\t\t\t\t\tremove.parentNode.removeChild( remove );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tscript = ret[i];\n\t\t\t\tif ( scripts && jQuery.nodeName( script, \"script\" ) && (!script.type || rscriptType.test( script.type )) ) {\n\t\t\t\t\tscripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( script.nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( script.getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( script );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnum = /^[\\-+]?(?:\\d*\\.)?\\d+$/i,\n\trnumnonpx = /^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\trmargin = /^margin/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\n\t// order is important!\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\treturn jQuery.access( this, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t}, name, value, arguments.length > 1 );\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {},\n\t\t\tret, name;\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// DEPRECATED in 1.3, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle, width,\n\t\t\tstyle = elem.style;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( (defaultView = elem.ownerDocument.defaultView) &&\n\t\t\t\t(computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// WebKit uses \"computed value (percentage if specified)\" instead of \"used value\" for margins\n\t\t// which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {\n\t\t\twidth = style.width;\n\t\t\tstyle.width = ret;\n\t\t\tret = computedStyle.width;\n\t\t\tstyle.width = width;\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( rnumnonpx.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\ti = name === \"width\" ? 1 : 0,\n\t\tlen = 4;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tfor ( ; i < len; i += 2 ) {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ];\n\t}\n\n\t// Computed unit is not pixels. Stop here and return.\n\tif ( rnumnonpx.test(val) ) {\n\t\treturn val;\n\t}\n\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tfor ( ; i < len; i += 2 ) {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val + \"px\";\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\treturn jQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\treturn rnum.test( value ) ?\n\t\t\t\tvalue + \"px\" :\n\t\t\t\tvalue;\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\treturn curCSS( elem, \"margin-right\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i,\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n\t\t\t\texpanded = {};\n\n\t\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n});\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = ( typeof s.data === \"string\" ) && /^application\\/x\\-www\\-form\\-urlencoded/.test( s.contentType );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t} catch( _ ) {\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( (display === \"\" && jQuery.css(elem, \"display\") === \"none\") ||\n\t\t\t\t\t\t!jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e, hooks, replace,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\t// first pass over propertys to expand / normalize\n\t\t\tfor ( p in prop ) {\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tif ( ( hooks = jQuery.cssHooks[ name ] ) && \"expand\" in hooks ) {\n\t\t\t\t\treplace = hooks.expand( prop[ name ] );\n\t\t\t\t\tdelete prop[ name ];\n\n\t\t\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t\t\t// also - reusing 'p' from above because we have the correct \"name\"\n\t\t\t\t\tfor ( p in replace ) {\n\t\t\t\t\t\tif ( ! ( p in prop ) ) {\n\t\t\t\t\t\t\tprop[ p ] = replace[ p ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( name in prop ) {\n\t\t\t\tval = prop[ name ];\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, index ) {\n\t\t\t\tvar hooks = data[ index ];\n\t\t\t\tjQuery.removeData( elem, index, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n\t\t\t\tstopQueue( this, data, index );\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ index ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ index ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p ) {\n\t\t\treturn p;\n\t\t},\n\t\tswing: function( p ) {\n\t\t\treturn ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tif ( self.options.hide ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t\t} else if ( self.options.show ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.end );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Ensure props that can't be negative don't go there on undershoot easing\njQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {\n\t// exclude marginTop, marginLeft, marginBottom and marginRight from this list\n\tif ( prop.indexOf( \"margin\" ) ) {\n\t\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( jQuery.support.boxModel ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar getOffset,\n\trtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tgetOffset = function( elem, doc, docElem, box ) {\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow( doc ),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tgetOffset = function( elem, doc, docElem ) {\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar elem = this[0],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn null;\n\t}\n\n\tif ( elem === doc.body ) {\n\t\treturn jQuery.offset.bodyOffset( elem );\n\t}\n\n\treturn getOffset( elem, doc, doc.documentElement );\n};\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t top ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tvar clientProp = \"client\" + name,\n\t\tscrollProp = \"scroll\" + name,\n\t\toffsetProp = \"offset\" + name;\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( value ) {\n\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\tvar doc, docElemProp, orig, ret;\n\n\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\t\tdoc = elem.document;\n\t\t\t\tdocElemProp = doc.documentElement[ clientProp ];\n\t\t\t\treturn jQuery.support.boxModel && docElemProp ||\n\t\t\t\t\tdoc.body && doc.body[ clientProp ] || docElemProp;\n\t\t\t}\n\n\t\t\t// Get document width or height\n\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t// when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]\n\t\t\t\t// so we can't use max, as it'll choose the incorrect offset[Width/Height]\n\t\t\t\t// instead we use the correct client[Width/Height]\n\t\t\t\t// support:IE6\n\t\t\t\tif ( doc[ clientProp ] >= doc[ scrollProp ] ) {\n\t\t\t\t\treturn doc[ clientProp ];\n\t\t\t\t}\n\n\t\t\t\treturn Math.max(\n\t\t\t\t\telem.body[ scrollProp ], doc[ scrollProp ],\n\t\t\t\t\telem.body[ offsetProp ], doc[ offsetProp ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get width or height on the element\n\t\t\tif ( value === undefined ) {\n\t\t\t\torig = jQuery.css( elem, type );\n\t\t\t\tret = parseFloat( orig );\n\t\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\t\t\t}\n\n\t\t\t// Set the width or height on the element\n\t\t\tjQuery( elem ).css( type, value );\n\t\t}, type, value, arguments.length, null );\n\t};\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );\n/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document){\n  var _jQuery = window.jQuery.noConflict(true);\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n\n/**\n * Setup file for the Scenario.\n * Must be first in the compilation/bootstrap list.\n */\n\n// Public namespace\nangular.scenario = angular.scenario || {};\n\n/**\n * Defines a new output format.\n *\n * @param {string} name the name of the new output format\n * @param {function()} fn function(context, runner) that generates the output\n */\nangular.scenario.output = angular.scenario.output || function(name, fn) {\n  angular.scenario.output[name] = fn;\n};\n\n/**\n * Defines a new DSL statement. If your factory function returns a Future\n * it's returned, otherwise the result is assumed to be a map of functions\n * for chaining. Chained functions are subject to the same rules.\n *\n * Note: All functions on the chain are bound to the chain scope so values\n *   set on \"this\" in your statement function are available in the chained\n *   functions.\n *\n * @param {string} name The name of the statement\n * @param {function()} fn Factory function(), return a function for\n *  the statement.\n */\nangular.scenario.dsl = angular.scenario.dsl || function(name, fn) {\n  angular.scenario.dsl[name] = function() {\n    function executeStatement(statement, args) {\n      var result = statement.apply(this, args);\n      if (angular.isFunction(result) || result instanceof angular.scenario.Future)\n        return result;\n      var self = this;\n      var chain = angular.extend({}, result);\n      angular.forEach(chain, function(value, name) {\n        if (angular.isFunction(value)) {\n          chain[name] = function() {\n            return executeStatement.call(self, value, arguments);\n          };\n        } else {\n          chain[name] = value;\n        }\n      });\n      return chain;\n    }\n    var statement = fn.apply(this, arguments);\n    return function() {\n      return executeStatement.call(this, statement, arguments);\n    };\n  };\n};\n\n/**\n * Defines a new matcher for use with the expects() statement. The value\n * this.actual (like in Jasmine) is available in your matcher to compare\n * against. Your function should return a boolean. The future is automatically\n * created for you.\n *\n * @param {string} name The name of the matcher\n * @param {function()} fn The matching function(expected).\n */\nangular.scenario.matcher = angular.scenario.matcher || function(name, fn) {\n  angular.scenario.matcher[name] = function(expected) {\n    var prefix = 'expect ' + this.future.name + ' ';\n    if (this.inverse) {\n      prefix += 'not ';\n    }\n    var self = this;\n    this.addFuture(prefix + name + ' ' + angular.toJson(expected),\n      function(done) {\n        var error;\n        self.actual = self.future.value;\n        if ((self.inverse && fn.call(self, expected)) ||\n            (!self.inverse && !fn.call(self, expected))) {\n          error = 'expected ' + angular.toJson(expected) +\n            ' but was ' + angular.toJson(self.actual);\n        }\n        done(error);\n    });\n  };\n};\n\n/**\n * Initialize the scenario runner and run !\n *\n * Access global window and document object\n * Access $runner through closure\n *\n * @param {Object=} config Config options\n */\nangular.scenario.setUpAndRun = function(config) {\n  var href = window.location.href;\n  var body = _jQuery(document.body);\n  var output = [];\n  var objModel = new angular.scenario.ObjectModel($runner);\n\n  if (config && config.scenario_output) {\n    output = config.scenario_output.split(',');\n  }\n\n  angular.forEach(angular.scenario.output, function(fn, name) {\n    if (!output.length || indexOf(output,name) != -1) {\n      var context = body.append('<div></div>').find('div:last');\n      context.attr('id', name);\n      fn.call({}, context, $runner, objModel);\n    }\n  });\n\n  if (!/^http/.test(href) && !/^https/.test(href)) {\n    body.append('<p id=\"system-error\"></p>');\n    body.find('#system-error').text(\n      'Scenario runner must be run using http or https. The protocol ' +\n      href.split(':')[0] + ':// is not supported.'\n    );\n    return;\n  }\n\n  var appFrame = body.append('<div id=\"application\"></div>').find('#application');\n  var application = new angular.scenario.Application(appFrame);\n\n  $runner.on('RunnerEnd', function() {\n    appFrame.css('display', 'none');\n    appFrame.find('iframe').attr('src', 'about:blank');\n  });\n\n  $runner.on('RunnerError', function(error) {\n    if (window.console) {\n      console.log(formatException(error));\n    } else {\n      // Do something for IE\n      alert(error);\n    }\n  });\n\n  $runner.run(application);\n};\n\n/**\n * Iterates through list with iterator function that must call the\n * continueFunction to continute iterating.\n *\n * @param {Array} list list to iterate over\n * @param {function()} iterator Callback function(value, continueFunction)\n * @param {function()} done Callback function(error, result) called when\n *   iteration finishes or an error occurs.\n */\nfunction asyncForEach(list, iterator, done) {\n  var i = 0;\n  function loop(error, index) {\n    if (index && index > i) {\n      i = index;\n    }\n    if (error || i >= list.length) {\n      done(error);\n    } else {\n      try {\n        iterator(list[i++], loop);\n      } catch (e) {\n        done(e);\n      }\n    }\n  }\n  loop();\n}\n\n/**\n * Formats an exception into a string with the stack trace, but limits\n * to a specific line length.\n *\n * @param {Object} error The exception to format, can be anything throwable\n * @param {Number=} [maxStackLines=5] max lines of the stack trace to include\n *  default is 5.\n */\nfunction formatException(error, maxStackLines) {\n  maxStackLines = maxStackLines || 5;\n  var message = error.toString();\n  if (error.stack) {\n    var stack = error.stack.split('\\n');\n    if (stack[0].indexOf(message) === -1) {\n      maxStackLines++;\n      stack.unshift(error.message);\n    }\n    message = stack.slice(0, maxStackLines).join('\\n');\n  }\n  return message;\n}\n\n/**\n * Returns a function that gets the file name and line number from a\n * location in the stack if available based on the call site.\n *\n * Note: this returns another function because accessing .stack is very\n * expensive in Chrome.\n *\n * @param {Number} offset Number of stack lines to skip\n */\nfunction callerFile(offset) {\n  var error = new Error();\n\n  return function() {\n    var line = (error.stack || '').split('\\n')[offset];\n\n    // Clean up the stack trace line\n    if (line) {\n      if (line.indexOf('@') !== -1) {\n        // Firefox\n        line = line.substring(line.indexOf('@')+1);\n      } else {\n        // Chrome\n        line = line.substring(line.indexOf('(')+1).replace(')', '');\n      }\n    }\n\n    return line || '';\n  };\n}\n\n/**\n * Triggers a browser event. Attempts to choose the right event if one is\n * not specified.\n *\n * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement\n * @param {string} type Optional event type.\n * @param {Array.<string>=} keys Optional list of pressed keys\n *        (valid values: 'alt', 'meta', 'shift', 'ctrl')\n */\nfunction browserTrigger(element, type, keys) {\n  if (element && !element.nodeName) element = element[0];\n  if (!element) return;\n  if (!type) {\n    type = {\n        'text':            'change',\n        'textarea':        'change',\n        'hidden':          'change',\n        'password':        'change',\n        'button':          'click',\n        'submit':          'click',\n        'reset':           'click',\n        'image':           'click',\n        'checkbox':        'click',\n        'radio':           'click',\n        'select-one':      'change',\n        'select-multiple': 'change'\n    }[lowercase(element.type)] || 'click';\n  }\n  if (lowercase(nodeName_(element)) == 'option') {\n    element.parentNode.value = element.value;\n    element = element.parentNode;\n    type = 'change';\n  }\n\n  keys = keys || [];\n  function pressed(key) {\n    return indexOf(keys, key) !== -1;\n  }\n\n  if (msie < 9) {\n    switch(element.type) {\n      case 'radio':\n      case 'checkbox':\n        element.checked = !element.checked;\n        break;\n    }\n    // WTF!!! Error: Unspecified error.\n    // Don't know why, but some elements when detached seem to be in inconsistent state and\n    // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)\n    // forcing the browser to compute the element position (by reading its CSS)\n    // puts the element in consistent state.\n    element.style.posLeft;\n\n    // TODO(vojta): create event objects with pressed keys to get it working on IE<9\n    var ret = element.fireEvent('on' + type);\n    if (lowercase(element.type) == 'submit') {\n      while(element) {\n        if (lowercase(element.nodeName) == 'form') {\n          element.fireEvent('onsubmit');\n          break;\n        }\n        element = element.parentNode;\n      }\n    }\n    return ret;\n  } else {\n    var evnt = document.createEvent('MouseEvents'),\n        originalPreventDefault = evnt.preventDefault,\n        iframe = _jQuery('#application iframe')[0],\n        appWindow = iframe ? iframe.contentWindow : window,\n        fakeProcessDefault = true,\n        finalProcessDefault,\n        angular = appWindow.angular || {};\n\n    // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208\n    angular['ff-684208-preventDefault'] = false;\n    evnt.preventDefault = function() {\n      fakeProcessDefault = false;\n      return originalPreventDefault.apply(evnt, arguments);\n    };\n\n    evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, pressed('ctrl'), pressed('alt'),\n                        pressed('shift'), pressed('meta'), 0, element);\n\n    element.dispatchEvent(evnt);\n    finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);\n\n    delete angular['ff-684208-preventDefault'];\n\n    return finalProcessDefault;\n  }\n}\n\n/**\n * Don't use the jQuery trigger method since it works incorrectly.\n *\n * jQuery notifies listeners and then changes the state of a checkbox and\n * does not create a real browser event. A real click changes the state of\n * the checkbox and then notifies listeners.\n *\n * To work around this we instead use our own handler that fires a real event.\n */\n(function(fn){\n  var parentTrigger = fn.trigger;\n  fn.trigger = function(type) {\n    if (/(click|change|keydown|blur|input)/.test(type)) {\n      var processDefaults = [];\n      this.each(function(index, node) {\n        processDefaults.push(browserTrigger(node, type));\n      });\n\n      // this is not compatible with jQuery - we return an array of returned values,\n      // so that scenario runner know whether JS code has preventDefault() of the event or not...\n      return processDefaults;\n    }\n    return parentTrigger.apply(this, arguments);\n  };\n})(_jQuery.fn);\n\n/**\n * Finds all bindings with the substring match of name and returns an\n * array of their values.\n *\n * @param {string} bindExp The name to match\n * @return {Array.<string>} String of binding values\n */\n_jQuery.fn.bindings = function(windowJquery, bindExp) {\n  var result = [], match,\n      bindSelector = '.ng-binding:visible';\n  if (angular.isString(bindExp)) {\n    bindExp = bindExp.replace(/\\s/g, '');\n    match = function (actualExp) {\n      if (actualExp) {\n        actualExp = actualExp.replace(/\\s/g, '');\n        if (actualExp == bindExp) return true;\n        if (actualExp.indexOf(bindExp) == 0) {\n          return actualExp.charAt(bindExp.length) == '|';\n        }\n      }\n    }\n  } else if (bindExp) {\n    match = function(actualExp) {\n      return actualExp && bindExp.exec(actualExp);\n    }\n  } else {\n    match = function(actualExp) {\n      return !!actualExp;\n    };\n  }\n  var selection = this.find(bindSelector);\n  if (this.is(bindSelector)) {\n    selection = selection.add(this);\n  }\n\n  function push(value) {\n    if (value == undefined) {\n      value = '';\n    } else if (typeof value != 'string') {\n      value = angular.toJson(value);\n    }\n    result.push('' + value);\n  }\n\n  selection.each(function() {\n    var element = windowJquery(this),\n        binding;\n    if (binding = element.data('$binding')) {\n      if (typeof binding == 'string') {\n        if (match(binding)) {\n          push(element.scope().$eval(binding));\n        }\n      } else {\n        if (!angular.isArray(binding)) {\n          binding = [binding];\n        }\n        for(var fns, j=0, jj=binding.length;  j<jj; j++) {\n          fns = binding[j];\n          if (fns.parts) {\n            fns = fns.parts;\n          } else {\n            fns = [fns];\n          }\n          for (var scope, fn, i = 0, ii = fns.length; i < ii; i++) {\n            if(match((fn = fns[i]).exp)) {\n              push(fn(scope = scope || element.scope()));\n            }\n          }\n        }\n      }\n    }\n  });\n  return result;\n};\n\n/**\n * Represents the application currently being tested and abstracts usage\n * of iframes or separate windows.\n *\n * @param {Object} context jQuery wrapper around HTML context.\n */\nangular.scenario.Application = function(context) {\n  this.context = context;\n  context.append(\n    '<h2>Current URL: <a href=\"about:blank\">None</a></h2>' +\n    '<div id=\"test-frames\"></div>'\n  );\n};\n\n/**\n * Gets the jQuery collection of frames. Don't use this directly because\n * frames may go stale.\n *\n * @private\n * @return {Object} jQuery collection\n */\nangular.scenario.Application.prototype.getFrame_ = function() {\n  return this.context.find('#test-frames iframe:last');\n};\n\n/**\n * Gets the window of the test runner frame. Always favor executeAction()\n * instead of this method since it prevents you from getting a stale window.\n *\n * @private\n * @return {Object} the window of the frame\n */\nangular.scenario.Application.prototype.getWindow_ = function() {\n  var contentWindow = this.getFrame_().prop('contentWindow');\n  if (!contentWindow)\n    throw 'Frame window is not accessible.';\n  return contentWindow;\n};\n\n/**\n * Changes the location of the frame.\n *\n * @param {string} url The URL. If it begins with a # then only the\n *   hash of the page is changed.\n * @param {function()} loadFn function($window, $document) Called when frame loads.\n * @param {function()} errorFn function(error) Called if any error when loading.\n */\nangular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorFn) {\n  var self = this;\n  var frame = this.getFrame_();\n  //TODO(esprehn): Refactor to use rethrow()\n  errorFn = errorFn || function(e) { throw e; };\n  if (url === 'about:blank') {\n    errorFn('Sandbox Error: Navigating to about:blank is not allowed.');\n  } else if (url.charAt(0) === '#') {\n    url = frame.attr('src').split('#')[0] + url;\n    frame.attr('src', url);\n    this.executeAction(loadFn);\n  } else {\n    frame.remove();\n    this.context.find('#test-frames').append('<iframe>');\n    frame = this.getFrame_();\n    frame.load(function() {\n      frame.unbind();\n      try {\n        self.executeAction(loadFn);\n      } catch (e) {\n        errorFn(e);\n      }\n    }).attr('src', url);\n  }\n  this.context.find('> h2 a').attr('href', url).text(url);\n};\n\n/**\n * Executes a function in the context of the tested application. Will wait\n * for all pending angular xhr requests before executing.\n *\n * @param {function()} action The callback to execute. function($window, $document)\n *  $document is a jQuery wrapped document.\n */\nangular.scenario.Application.prototype.executeAction = function(action) {\n  var self = this;\n  var $window = this.getWindow_();\n  if (!$window.document) {\n    throw 'Sandbox Error: Application document not accessible.';\n  }\n  if (!$window.angular) {\n    return action.call(this, $window, _jQuery($window.document));\n  }\n  angularInit($window.document, function(element) {\n    var $injector = $window.angular.element(element).injector();\n    var $element = _jQuery(element);\n\n    $element.injector = function() {\n      return $injector;\n    };\n\n    $injector.invoke(function($browser){\n      $browser.notifyWhenNoOutstandingRequests(function() {\n        action.call(self, $window, $element);\n      });\n    });\n  });\n};\n\n/**\n * The representation of define blocks. Don't used directly, instead use\n * define() in your tests.\n *\n * @param {string} descName Name of the block\n * @param {Object} parent describe or undefined if the root.\n */\nangular.scenario.Describe = function(descName, parent) {\n  this.only = parent && parent.only;\n  this.beforeEachFns = [];\n  this.afterEachFns = [];\n  this.its = [];\n  this.children = [];\n  this.name = descName;\n  this.parent = parent;\n  this.id = angular.scenario.Describe.id++;\n\n  /**\n   * Calls all before functions.\n   */\n  var beforeEachFns = this.beforeEachFns;\n  this.setupBefore = function() {\n    if (parent) parent.setupBefore.call(this);\n    angular.forEach(beforeEachFns, function(fn) { fn.call(this); }, this);\n  };\n\n  /**\n   * Calls all after functions.\n   */\n  var afterEachFns = this.afterEachFns;\n  this.setupAfter  = function() {\n    angular.forEach(afterEachFns, function(fn) { fn.call(this); }, this);\n    if (parent) parent.setupAfter.call(this);\n  };\n};\n\n// Shared Unique ID generator for every describe block\nangular.scenario.Describe.id = 0;\n\n// Shared Unique ID generator for every it (spec)\nangular.scenario.Describe.specId = 0;\n\n/**\n * Defines a block to execute before each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.beforeEach = function(body) {\n  this.beforeEachFns.push(body);\n};\n\n/**\n * Defines a block to execute after each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.afterEach = function(body) {\n  this.afterEachFns.push(body);\n};\n\n/**\n * Creates a new describe block that's a child of this one.\n *\n * @param {string} name Name of the block. Appended to the parent block's name.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.describe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Same as describe() but makes ddescribe blocks the only to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.ddescribe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  child.only = true;\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Use to disable a describe block.\n */\nangular.scenario.Describe.prototype.xdescribe = angular.noop;\n\n/**\n * Defines a test.\n *\n * @param {string} name Name of the test.\n * @param {function()} vody Body of the block.\n */\nangular.scenario.Describe.prototype.it = function(name, body) {\n  this.its.push({\n    id: angular.scenario.Describe.specId++,\n    definition: this,\n    only: this.only,\n    name: name,\n    before: this.setupBefore,\n    body: body,\n    after: this.setupAfter\n  });\n};\n\n/**\n * Same as it() but makes iit tests the only test to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.iit = function(name, body) {\n  this.it.apply(this, arguments);\n  this.its[this.its.length-1].only = true;\n};\n\n/**\n * Use to disable a test block.\n */\nangular.scenario.Describe.prototype.xit = angular.noop;\n\n/**\n * Gets an array of functions representing all the tests (recursively).\n * that can be executed with SpecRunner's.\n *\n * @return {Array<Object>} Array of it blocks {\n *   definition : Object // parent Describe\n *   only: boolean\n *   name: string\n *   before: Function\n *   body: Function\n *   after: Function\n *  }\n */\nangular.scenario.Describe.prototype.getSpecs = function() {\n  var specs = arguments[0] || [];\n  angular.forEach(this.children, function(child) {\n    child.getSpecs(specs);\n  });\n  angular.forEach(this.its, function(it) {\n    specs.push(it);\n  });\n  var only = [];\n  angular.forEach(specs, function(it) {\n    if (it.only) {\n      only.push(it);\n    }\n  });\n  return (only.length && only) || specs;\n};\n\n/**\n * A future action in a spec.\n *\n * @param {string} name of the future action\n * @param {function()} future callback(error, result)\n * @param {function()} Optional. function that returns the file/line number.\n */\nangular.scenario.Future = function(name, behavior, line) {\n  this.name = name;\n  this.behavior = behavior;\n  this.fulfilled = false;\n  this.value = undefined;\n  this.parser = angular.identity;\n  this.line = line || function() { return ''; };\n};\n\n/**\n * Executes the behavior of the closure.\n *\n * @param {function()} doneFn Callback function(error, result)\n */\nangular.scenario.Future.prototype.execute = function(doneFn) {\n  var self = this;\n  this.behavior(function(error, result) {\n    self.fulfilled = true;\n    if (result) {\n      try {\n        result = self.parser(result);\n      } catch(e) {\n        error = e;\n      }\n    }\n    self.value = error || result;\n    doneFn(error, result);\n  });\n};\n\n/**\n * Configures the future to convert it's final with a function fn(value)\n *\n * @param {function()} fn function(value) that returns the parsed value\n */\nangular.scenario.Future.prototype.parsedWith = function(fn) {\n  this.parser = fn;\n  return this;\n};\n\n/**\n * Configures the future to parse it's final value from JSON\n * into objects.\n */\nangular.scenario.Future.prototype.fromJson = function() {\n  return this.parsedWith(angular.fromJson);\n};\n\n/**\n * Configures the future to convert it's final value from objects\n * into JSON.\n */\nangular.scenario.Future.prototype.toJson = function() {\n  return this.parsedWith(angular.toJson);\n};\n\n/**\n * Maintains an object tree from the runner events.\n *\n * @param {Object} runner The scenario Runner instance to connect to.\n *\n * TODO(esprehn): Every output type creates one of these, but we probably\n *  want one global shared instance. Need to handle events better too\n *  so the HTML output doesn't need to do spec model.getSpec(spec.id)\n *  silliness.\n *\n * TODO(vojta) refactor on, emit methods (from all objects) - use inheritance\n */\nangular.scenario.ObjectModel = function(runner) {\n  var self = this;\n\n  this.specMap = {};\n  this.listeners = [];\n  this.value = {\n    name: '',\n    children: {}\n  };\n\n  runner.on('SpecBegin', function(spec) {\n    var block = self.value,\n        definitions = [];\n\n    angular.forEach(self.getDefinitionPath(spec), function(def) {\n      if (!block.children[def.name]) {\n        block.children[def.name] = {\n          id: def.id,\n          name: def.name,\n          children: {},\n          specs: {}\n        };\n      }\n      block = block.children[def.name];\n      definitions.push(def.name);\n    });\n\n    var it = self.specMap[spec.id] =\n             block.specs[spec.name] =\n             new angular.scenario.ObjectModel.Spec(spec.id, spec.name, definitions);\n\n    // forward the event\n    self.emit('SpecBegin', it);\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var it = self.getSpec(spec.id);\n    it.status = 'error';\n    it.error = error;\n\n    // forward the event\n    self.emit('SpecError', it, error);\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    complete(it);\n\n    // forward the event\n    self.emit('SpecEnd', it);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var it = self.getSpec(spec.id);\n    var step = new angular.scenario.ObjectModel.Step(step.name);\n    it.steps.push(step);\n\n    // forward the event\n    self.emit('StepBegin', it, step);\n  });\n\n  runner.on('StepEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    var step = it.getLastStep();\n    if (step.name !== step.name)\n      throw 'Events fired in the wrong order. Step names don\\'t match.';\n    complete(step);\n\n    // forward the event\n    self.emit('StepEnd', it, step);\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('failure', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepFailure', it, modelStep, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('error', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepError', it, modelStep, error);\n  });\n\n  runner.on('RunnerBegin', function() {\n    self.emit('RunnerBegin');\n  });\n  runner.on('RunnerEnd', function() {\n    self.emit('RunnerEnd');\n  });\n\n  function complete(item) {\n    item.endTime = new Date().getTime();\n    item.duration = item.endTime - item.startTime;\n    item.status = item.status || 'success';\n  }\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName Name of the event to add a handler for\n * @param {function()} listener Function that will be called when event is fired\n */\nangular.scenario.ObjectModel.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.ObjectModel.prototype.emit = function(eventName) {\n  var self = this,\n      args = Array.prototype.slice.call(arguments, 1),\n      eventName = eventName.toLowerCase();\n\n  if (this.listeners[eventName]) {\n    angular.forEach(this.listeners[eventName], function(listener) {\n      listener.apply(self, args);\n    });\n  }\n};\n\n/**\n * Computes the path of definition describe blocks that wrap around\n * this spec.\n *\n * @param spec Spec to compute the path for.\n * @return {Array<Describe>} The describe block path\n */\nangular.scenario.ObjectModel.prototype.getDefinitionPath = function(spec) {\n  var path = [];\n  var currentDefinition = spec.definition;\n  while (currentDefinition && currentDefinition.name) {\n    path.unshift(currentDefinition);\n    currentDefinition = currentDefinition.parent;\n  }\n  return path;\n};\n\n/**\n * Gets a spec by id.\n *\n * @param {string} The id of the spec to get the object for.\n * @return {Object} the Spec instance\n */\nangular.scenario.ObjectModel.prototype.getSpec = function(id) {\n  return this.specMap[id];\n};\n\n/**\n * A single it block.\n *\n * @param {string} id Id of the spec\n * @param {string} name Name of the spec\n * @param {Array<string>=} definitionNames List of all describe block names that wrap this spec\n */\nangular.scenario.ObjectModel.Spec = function(id, name, definitionNames) {\n  this.id = id;\n  this.name = name;\n  this.startTime = new Date().getTime();\n  this.steps = [];\n  this.fullDefinitionName = (definitionNames || []).join(' ');\n};\n\n/**\n * Adds a new step to the Spec.\n *\n * @param {string} step Name of the step (really name of the future)\n * @return {Object} the added step\n */\nangular.scenario.ObjectModel.Spec.prototype.addStep = function(name) {\n  var step = new angular.scenario.ObjectModel.Step(name);\n  this.steps.push(step);\n  return step;\n};\n\n/**\n * Gets the most recent step.\n *\n * @return {Object} the step\n */\nangular.scenario.ObjectModel.Spec.prototype.getLastStep = function() {\n  return this.steps[this.steps.length-1];\n};\n\n/**\n * Set status of the Spec from given Step\n *\n * @param {angular.scenario.ObjectModel.Step} step\n */\nangular.scenario.ObjectModel.Spec.prototype.setStatusFromStep = function(step) {\n  if (!this.status || step.status == 'error') {\n    this.status = step.status;\n    this.error = step.error;\n    this.line = step.line;\n  }\n};\n\n/**\n * A single step inside a Spec.\n *\n * @param {string} step Name of the step\n */\nangular.scenario.ObjectModel.Step = function(name) {\n  this.name = name;\n  this.startTime = new Date().getTime();\n};\n\n/**\n * Helper method for setting all error status related properties\n *\n * @param {string} status\n * @param {string} error\n * @param {string} line\n */\nangular.scenario.ObjectModel.Step.prototype.setErrorStatus = function(status, error, line) {\n  this.status = status;\n  this.error = error;\n  this.line = line;\n};\n\n/**\n * Runner for scenarios\n *\n * Has to be initialized before any test is loaded,\n * because it publishes the API into window (global space).\n */\nangular.scenario.Runner = function($window) {\n  this.listeners = [];\n  this.$window = $window;\n  this.rootDescribe = new angular.scenario.Describe();\n  this.currentDescribe = this.rootDescribe;\n  this.api = {\n    it: this.it,\n    iit: this.iit,\n    xit: angular.noop,\n    describe: this.describe,\n    ddescribe: this.ddescribe,\n    xdescribe: angular.noop,\n    beforeEach: this.beforeEach,\n    afterEach: this.afterEach\n  };\n  angular.forEach(this.api, angular.bind(this, function(fn, key) {\n    this.$window[key] = angular.bind(this, fn);\n  }));\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.Runner.prototype.emit = function(eventName) {\n  var self = this;\n  var args = Array.prototype.slice.call(arguments, 1);\n  eventName = eventName.toLowerCase();\n  if (!this.listeners[eventName])\n    return;\n  angular.forEach(this.listeners[eventName], function(listener) {\n    listener.apply(self, args);\n  });\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName The name of the event to add a handler for\n * @param {string} listener The fn(...) that takes the extra arguments from emit()\n */\nangular.scenario.Runner.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Defines a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.describe = function(name, body) {\n  var self = this;\n  this.currentDescribe.describe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Same as describe, but makes ddescribe the only blocks to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.ddescribe = function(name, body) {\n  var self = this;\n  this.currentDescribe.ddescribe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Defines a test in a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.it = function(name, body) {\n  this.currentDescribe.it(name, body);\n};\n\n/**\n * Same as it, but makes iit tests the only tests to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.iit = function(name, body) {\n  this.currentDescribe.iit(name, body);\n};\n\n/**\n * Defines a function to be called before each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.beforeEach = function(body) {\n  this.currentDescribe.beforeEach(body);\n};\n\n/**\n * Defines a function to be called after each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.afterEach = function(body) {\n  this.currentDescribe.afterEach(body);\n};\n\n/**\n * Creates a new spec runner.\n *\n * @private\n * @param {Object} scope parent scope\n */\nangular.scenario.Runner.prototype.createSpecRunner_ = function(scope) {\n  var child = scope.$new();\n  var Cls = angular.scenario.SpecRunner;\n\n  // Export all the methods to child scope manually as now we don't mess controllers with scopes\n  // TODO(vojta): refactor scenario runner so that these objects are not tightly coupled as current\n  for (var name in Cls.prototype)\n    child[name] = angular.bind(child, Cls.prototype[name]);\n\n  Cls.call(child);\n  return child;\n};\n\n/**\n * Runs all the loaded tests with the specified runner class on the\n * provided application.\n *\n * @param {angular.scenario.Application} application App to remote control.\n */\nangular.scenario.Runner.prototype.run = function(application) {\n  var self = this;\n  var $root = angular.injector(['ng']).get('$rootScope');\n  angular.extend($root, this);\n  angular.forEach(angular.scenario.Runner.prototype, function(fn, name) {\n    $root[name] = angular.bind(self, fn);\n  });\n  $root.application = application;\n  $root.emit('RunnerBegin');\n  asyncForEach(this.rootDescribe.getSpecs(), function(spec, specDone) {\n    var dslCache = {};\n    var runner = self.createSpecRunner_($root);\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      dslCache[key] = fn.call($root);\n    });\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      self.$window[key] = function() {\n        var line = callerFile(3);\n        var scope = runner.$new();\n\n        // Make the dsl accessible on the current chain\n        scope.dsl = {};\n        angular.forEach(dslCache, function(fn, key) {\n          scope.dsl[key] = function() {\n            return dslCache[key].apply(scope, arguments);\n          };\n        });\n\n        // Make these methods work on the current chain\n        scope.addFuture = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFuture.apply(scope, arguments);\n        };\n        scope.addFutureAction = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFutureAction.apply(scope, arguments);\n        };\n\n        return scope.dsl[key].apply(scope, arguments);\n      };\n    });\n    runner.run(spec, function() {\n      runner.$destroy();\n      specDone.apply(this, arguments);\n    });\n  },\n  function(error) {\n    if (error) {\n      self.emit('RunnerError', error);\n    }\n    self.emit('RunnerEnd');\n  });\n};\n\n/**\n * This class is the \"this\" of the it/beforeEach/afterEach method.\n * Responsibilities:\n *   - \"this\" for it/beforeEach/afterEach\n *   - keep state for single it/beforeEach/afterEach execution\n *   - keep track of all of the futures to execute\n *   - run single spec (execute each future)\n */\nangular.scenario.SpecRunner = function() {\n  this.futures = [];\n  this.afterIndex = 0;\n};\n\n/**\n * Executes a spec which is an it block with associated before/after functions\n * based on the describe nesting.\n *\n * @param {Object} spec A spec object\n * @param {function()} specDone function that is called when the spec finshes. Function(error, index)\n */\nangular.scenario.SpecRunner.prototype.run = function(spec, specDone) {\n  var self = this;\n  this.spec = spec;\n\n  this.emit('SpecBegin', spec);\n\n  try {\n    spec.before.call(this);\n    spec.body.call(this);\n    this.afterIndex = this.futures.length;\n    spec.after.call(this);\n  } catch (e) {\n    this.emit('SpecError', spec, e);\n    this.emit('SpecEnd', spec);\n    specDone();\n    return;\n  }\n\n  var handleError = function(error, done) {\n    if (self.error) {\n      return done();\n    }\n    self.error = true;\n    done(null, self.afterIndex);\n  };\n\n  asyncForEach(\n    this.futures,\n    function(future, futureDone) {\n      self.step = future;\n      self.emit('StepBegin', spec, future);\n      try {\n        future.execute(function(error) {\n          if (error) {\n            self.emit('StepFailure', spec, future, error);\n            self.emit('StepEnd', spec, future);\n            return handleError(error, futureDone);\n          }\n          self.emit('StepEnd', spec, future);\n          self.$window.setTimeout(function() { futureDone(); }, 0);\n        });\n      } catch (e) {\n        self.emit('StepError', spec, future, e);\n        self.emit('StepEnd', spec, future);\n        handleError(e, futureDone);\n      }\n    },\n    function(e) {\n      if (e) {\n        self.emit('SpecError', spec, e);\n      }\n      self.emit('SpecEnd', spec);\n      // Call done in a timeout so exceptions don't recursively\n      // call this function\n      self.$window.setTimeout(function() { specDone(); }, 0);\n    }\n  );\n};\n\n/**\n * Adds a new future action.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFuture = function(name, behavior, line) {\n  var future = new angular.scenario.Future(name, angular.bind(this, behavior), line);\n  this.futures.push(future);\n  return future;\n};\n\n/**\n * Adds a new future action to be executed on the application window.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior, line) {\n  var self = this;\n  var NG = /\\[ng\\\\\\:/;\n  return this.addFuture(name, function(done) {\n    this.application.executeAction(function($window, $document) {\n\n      //TODO(esprehn): Refactor this so it doesn't need to be in here.\n      $document.elements = function(selector) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        selector = (self.selector || '') + ' ' + (selector || '');\n        selector = _jQuery.trim(selector) || '*';\n        angular.forEach(args, function(value, index) {\n          selector = selector.replace('$' + (index + 1), value);\n        });\n        var result = $document.find(selector);\n        if (selector.match(NG)) {\n          angular.forEach(['[ng-','[data-ng-','[x-ng-'], function(value, index){\n            result = result.add(selector.replace(NG, value), $document);\n          });\n        }\n        if (!result.length) {\n          throw {\n            type: 'selector',\n            message: 'Selector ' + selector + ' did not match any elements.'\n          };\n        }\n\n        return result;\n      };\n\n      try {\n        behavior.call(self, $window, $document, done);\n      } catch(e) {\n        if (e.type && e.type === 'selector') {\n          done(e.message);\n        } else {\n          throw e;\n        }\n      }\n    });\n  }, line);\n};\n\n/**\n * Shared DSL statements that are useful to all scenarios.\n */\n\n /**\n * Usage:\n *    pause() pauses until you call resume() in the console\n */\nangular.scenario.dsl('pause', function() {\n  return function() {\n    return this.addFuture('pausing for you to resume', function(done) {\n      this.emit('InteractivePause', this.spec, this.step);\n      this.$window.resume = function() { done(); };\n    });\n  };\n});\n\n/**\n * Usage:\n *    sleep(seconds) pauses the test for specified number of seconds\n */\nangular.scenario.dsl('sleep', function() {\n  return function(time) {\n    return this.addFuture('sleep for ' + time + ' seconds', function(done) {\n      this.$window.setTimeout(function() { done(null, time * 1000); }, time * 1000);\n    });\n  };\n});\n\n/**\n * Usage:\n *    browser().navigateTo(url) Loads the url into the frame\n *    browser().navigateTo(url, fn) where fn(url) is called and returns the URL to navigate to\n *    browser().reload() refresh the page (reload the same URL)\n *    browser().window.href() window.location.href\n *    browser().window.path() window.location.pathname\n *    browser().window.search() window.location.search\n *    browser().window.hash() window.location.hash without # prefix\n *    browser().location().url() see ng.$location#url\n *    browser().location().path() see ng.$location#path\n *    browser().location().search() see ng.$location#search\n *    browser().location().hash() see ng.$location#hash\n */\nangular.scenario.dsl('browser', function() {\n  var chain = {};\n\n  chain.navigateTo = function(url, delegate) {\n    var application = this.application;\n    return this.addFuture(\"browser navigate to '\" + url + \"'\", function(done) {\n      if (delegate) {\n        url = delegate.call(this, url);\n      }\n      application.navigateTo(url, function() {\n        done(null, url);\n      }, done);\n    });\n  };\n\n  chain.reload = function() {\n    var application = this.application;\n    return this.addFutureAction('browser reload', function($window, $document, done) {\n      var href = $window.location.href;\n      application.navigateTo(href, function() {\n        done(null, href);\n      }, done);\n    });\n  };\n\n  chain.window = function() {\n    var api = {};\n\n    api.href = function() {\n      return this.addFutureAction('window.location.href', function($window, $document, done) {\n        done(null, $window.location.href);\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('window.location.path', function($window, $document, done) {\n        done(null, $window.location.pathname);\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('window.location.search', function($window, $document, done) {\n        done(null, $window.location.search);\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('window.location.hash', function($window, $document, done) {\n        done(null, $window.location.hash.replace('#', ''));\n      });\n    };\n\n    return api;\n  };\n\n  chain.location = function() {\n    var api = {};\n\n    api.url = function() {\n      return this.addFutureAction('$location.url()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').url());\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('$location.path()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').path());\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('$location.search()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').search());\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('$location.hash()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').hash());\n      });\n    };\n\n    return api;\n  };\n\n  return function() {\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    expect(future).{matcher} where matcher is one of the matchers defined\n *    with angular.scenario.matcher\n *\n * ex. expect(binding(\"name\")).toEqual(\"Elliott\")\n */\nangular.scenario.dsl('expect', function() {\n  var chain = angular.extend({}, angular.scenario.matcher);\n\n  chain.not = function() {\n    this.inverse = true;\n    return chain;\n  };\n\n  return function(future) {\n    this.future = future;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    using(selector, label) scopes the next DSL element selection\n *\n * ex.\n *   using('#foo', \"'Foo' text field\").input('bar')\n */\nangular.scenario.dsl('using', function() {\n  return function(selector, label) {\n    this.selector = _jQuery.trim((this.selector||'') + ' ' + selector);\n    if (angular.isString(label) && label.length) {\n      this.label = label + ' ( ' + this.selector + ' )';\n    } else {\n      this.label = this.selector;\n    }\n    return this.dsl;\n  };\n});\n\n/**\n * Usage:\n *    binding(name) returns the value of the first matching binding\n */\nangular.scenario.dsl('binding', function() {\n  return function(name) {\n    return this.addFutureAction(\"select binding '\" + name + \"'\", function($window, $document, done) {\n      var values = $document.elements().bindings($window.angular.element, name);\n      if (!values.length) {\n        return done(\"Binding selector '\" + name + \"' did not match.\");\n      }\n      done(null, values[0]);\n    });\n  };\n});\n\n/**\n * Usage:\n *    input(name).enter(value) enters value in input with specified name\n *    input(name).check() checks checkbox\n *    input(name).select(value) selects the radio button with specified name/value\n *    input(name).val() returns the value of the input.\n */\nangular.scenario.dsl('input', function() {\n  var chain = {};\n  var supportInputEvent =  'oninput' in document.createElement('div') && msie != 9;\n\n  chain.enter = function(value, event) {\n    return this.addFutureAction(\"input '\" + this.name + \"' enter '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      input.val(value);\n      input.trigger(event || (supportInputEvent ? 'input' : 'change'));\n      done();\n    });\n  };\n\n  chain.check = function() {\n    return this.addFutureAction(\"checkbox '\" + this.name + \"' toggle\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':checkbox');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.select = function(value) {\n    return this.addFutureAction(\"radio button '\" + this.name + \"' toggle '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.\n        elements('[ng\\\\:model=\"$1\"][value=\"$2\"]', this.name, value).filter(':radio');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.val = function() {\n    return this.addFutureAction(\"return input val\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      done(null,input.val());\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n\n/**\n * Usage:\n *    repeater('#products table', 'Product List').count() number of rows\n *    repeater('#products table', 'Product List').row(1) all bindings in row as an array\n *    repeater('#products table', 'Product List').column('product.name') all values across all rows in an array\n */\nangular.scenario.dsl('repeater', function() {\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.column = function(binding) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' column '\" + binding + \"'\", function($window, $document, done) {\n      done(null, $document.elements().bindings($window.angular.element, binding));\n    });\n  };\n\n  chain.row = function(index) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' row '\" + index + \"'\", function($window, $document, done) {\n      var matches = $document.elements().slice(index, index + 1);\n      if (!matches.length)\n        return done('row ' + index + ' out of bounds');\n      done(null, matches.bindings($window.angular.element));\n    });\n  };\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    select(name).option('value') select one option\n *    select(name).options('value1', 'value2', ...) select options from a multi select\n */\nangular.scenario.dsl('select', function() {\n  var chain = {};\n\n  chain.option = function(value) {\n    return this.addFutureAction(\"select '\" + this.name + \"' option '\" + value + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[ng\\\\:model=\"$1\"]', this.name);\n      var option = select.find('option[value=\"' + value + '\"]');\n      if (option.length) {\n        select.val(value);\n      } else {\n        option = select.find('option:contains(\"' + value + '\")');\n        if (option.length) {\n          select.val(option.val());\n        }\n      }\n      select.trigger('change');\n      done();\n    });\n  };\n\n  chain.options = function() {\n    var values = arguments;\n    return this.addFutureAction(\"select '\" + this.name + \"' options '\" + values + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[multiple][ng\\\\:model=\"$1\"]', this.name);\n      select.val(values);\n      select.trigger('change');\n      done();\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    element(selector, label).count() get the number of elements that match selector\n *    element(selector, label).click() clicks an element\n *    element(selector, label).query(fn) executes fn(selectedElements, done)\n *    element(selector, label).{method}() gets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(value) sets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(key) gets the value (as defined by jQuery, ex. attr)\n *    element(selector, label).{method}(key, value) sets the value (as defined by jQuery, ex. attr)\n */\nangular.scenario.dsl('element', function() {\n  var KEY_VALUE_METHODS = ['attr', 'css', 'prop'];\n  var VALUE_METHODS = [\n    'val', 'text', 'html', 'height', 'innerHeight', 'outerHeight', 'width',\n    'innerWidth', 'outerWidth', 'position', 'scrollLeft', 'scrollTop', 'offset'\n  ];\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.click = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' click\", function($window, $document, done) {\n      var elements = $document.elements();\n      var href = elements.attr('href');\n      var eventProcessDefault = elements.trigger('click')[0];\n\n      if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {\n        this.application.navigateTo(href, function() {\n          done();\n        }, done);\n      } else {\n        done();\n      }\n    });\n  };\n\n  chain.query = function(fn) {\n    return this.addFutureAction('element ' + this.label + ' custom query', function($window, $document, done) {\n      fn.call(this, $document.elements(), done);\n    });\n  };\n\n  angular.forEach(KEY_VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(name, value) {\n      var args = arguments,\n          futureName = (args.length == 1)\n              ? \"element '\" + this.label + \"' get \" + methodName + \" '\" + name + \"'\"\n              : \"element '\" + this.label + \"' set \" + methodName + \" '\" + name + \"' to \" + \"'\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  angular.forEach(VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(value) {\n      var args = arguments,\n          futureName = (args.length == 0)\n              ? \"element '\" + this.label + \"' \" + methodName\n              : futureName = \"element '\" + this.label + \"' set \" + methodName + \" to '\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Matchers for implementing specs. Follows the Jasmine spec conventions.\n */\n\nangular.scenario.matcher('toEqual', function(expected) {\n  return angular.equals(this.actual, expected);\n});\n\nangular.scenario.matcher('toBe', function(expected) {\n  return this.actual === expected;\n});\n\nangular.scenario.matcher('toBeDefined', function() {\n  return angular.isDefined(this.actual);\n});\n\nangular.scenario.matcher('toBeTruthy', function() {\n  return this.actual;\n});\n\nangular.scenario.matcher('toBeFalsy', function() {\n  return !this.actual;\n});\n\nangular.scenario.matcher('toMatch', function(expected) {\n  return new RegExp(expected).test(this.actual);\n});\n\nangular.scenario.matcher('toBeNull', function() {\n  return this.actual === null;\n});\n\nangular.scenario.matcher('toContain', function(expected) {\n  return includes(this.actual, expected);\n});\n\nangular.scenario.matcher('toBeLessThan', function(expected) {\n  return this.actual < expected;\n});\n\nangular.scenario.matcher('toBeGreaterThan', function(expected) {\n  return this.actual > expected;\n});\n\n/**\n * User Interface for the Scenario Runner.\n *\n * TODO(esprehn): This should be refactored now that ObjectModel exists\n *  to use angular bindings for the UI.\n */\nangular.scenario.output('html', function(context, runner, model) {\n  var specUiMap = {},\n      lastStepUiMap = {};\n\n  context.append(\n    '<div id=\"header\">' +\n    '  <h1><span class=\"angular\">AngularJS</span>: Scenario Test Runner</h1>' +\n    '  <ul id=\"status-legend\" class=\"status-display\">' +\n    '    <li class=\"status-error\">0 Errors</li>' +\n    '    <li class=\"status-failure\">0 Failures</li>' +\n    '    <li class=\"status-success\">0 Passed</li>' +\n    '  </ul>' +\n    '</div>' +\n    '<div id=\"specs\">' +\n    '  <div class=\"test-children\"></div>' +\n    '</div>'\n  );\n\n  runner.on('InteractivePause', function(spec) {\n    var ui = lastStepUiMap[spec.id];\n    ui.find('.test-title').\n      html('paused... <a href=\"javascript:resume()\">resume</a> when ready.');\n  });\n\n  runner.on('SpecBegin', function(spec) {\n    var ui = findContext(spec);\n    ui.find('> .tests').append(\n      '<li class=\"status-pending test-it\"></li>'\n    );\n    ui = ui.find('> .tests li:last');\n    ui.append(\n      '<div class=\"test-info\">' +\n      '  <p class=\"test-title\">' +\n      '    <span class=\"timer-result\"></span>' +\n      '    <span class=\"test-name\"></span>' +\n      '  </p>' +\n      '</div>' +\n      '<div class=\"scrollpane\">' +\n      '  <ol class=\"test-actions\"></ol>' +\n      '</div>'\n    );\n    ui.find('> .test-info .test-name').text(spec.name);\n    ui.find('> .test-info').click(function() {\n      var scrollpane = ui.find('> .scrollpane');\n      var actions = scrollpane.find('> .test-actions');\n      var name = context.find('> .test-info .test-name');\n      if (actions.find(':visible').length) {\n        actions.hide();\n        name.removeClass('open').addClass('closed');\n      } else {\n        actions.show();\n        scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n        name.removeClass('closed').addClass('open');\n      }\n    });\n\n    specUiMap[spec.id] = ui;\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var ui = specUiMap[spec.id];\n    ui.append('<pre></pre>');\n    ui.find('> pre').text(formatException(error));\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    ui.removeClass('status-pending');\n    ui.addClass('status-' + spec.status);\n    ui.find(\"> .test-info .timer-result\").text(spec.duration + \"ms\");\n    if (spec.status === 'success') {\n      ui.find('> .test-info .test-name').addClass('closed');\n      ui.find('> .scrollpane .test-actions').hide();\n    }\n    updateTotals(spec.status);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    ui.find('> .scrollpane .test-actions').append('<li class=\"status-pending\"></li>');\n    var stepUi = lastStepUiMap[spec.id] = ui.find('> .scrollpane .test-actions li:last');\n    stepUi.append(\n      '<div class=\"timer-result\"></div>' +\n      '<div class=\"test-title\"></div>'\n    );\n    stepUi.find('> .test-title').text(step.name);\n    var scrollpane = stepUi.parents('.scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepEnd', function(spec, step) {\n    var stepUi = lastStepUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    stepUi.find('.timer-result').text(step.duration + 'ms');\n    stepUi.removeClass('status-pending');\n    stepUi.addClass('status-' + step.status);\n    var scrollpane = specUiMap[spec.id].find('> .scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  /**\n   * Finds the context of a spec block defined by the passed definition.\n   *\n   * @param {Object} The definition created by the Describe object.\n   */\n  function findContext(spec) {\n    var currentContext = context.find('#specs');\n    angular.forEach(model.getDefinitionPath(spec), function(defn) {\n      var id = 'describe-' + defn.id;\n      if (!context.find('#' + id).length) {\n        currentContext.find('> .test-children').append(\n          '<div class=\"test-describe\" id=\"' + id + '\">' +\n          '  <h2></h2>' +\n          '  <div class=\"test-children\"></div>' +\n          '  <ul class=\"tests\"></ul>' +\n          '</div>'\n        );\n        context.find('#' + id).find('> h2').text('describe: ' + defn.name);\n      }\n      currentContext = context.find('#' + id);\n    });\n    return context.find('#describe-' + spec.definition.id);\n  }\n\n  /**\n   * Updates the test counter for the status.\n   *\n   * @param {string} the status.\n   */\n  function updateTotals(status) {\n    var legend = context.find('#status-legend .status-' + status);\n    var parts = legend.text().split(' ');\n    var value = (parts[0] * 1) + 1;\n    legend.text(value + ' ' + parts[1]);\n  }\n\n  /**\n   * Add an error to a step.\n   *\n   * @param {Object} The JQuery wrapped context\n   * @param {function()} fn() that should return the file/line number of the error\n   * @param {Object} the error.\n   */\n  function addError(context, line, error) {\n    context.find('.test-title').append('<pre></pre>');\n    var message = _jQuery.trim(line() + '\\n\\n' + formatException(error));\n    context.find('.test-title pre:last').text(message);\n  }\n});\n\n/**\n * Generates JSON output into a context.\n */\nangular.scenario.output('json', function(context, runner, model) {\n  model.on('RunnerEnd', function() {\n    context.text(angular.toJson(model.value));\n  });\n});\n\n/**\n * Generates XML output into a context.\n */\nangular.scenario.output('xml', function(context, runner, model) {\n  var $ = function(args) {return new context.init(args);};\n  model.on('RunnerEnd', function() {\n    var scenario = $('<scenario></scenario>');\n    context.append(scenario);\n    serializeXml(scenario, model.value);\n  });\n\n  /**\n   * Convert the tree into XML.\n   *\n   * @param {Object} context jQuery context to add the XML to.\n   * @param {Object} tree node to serialize\n   */\n  function serializeXml(context, tree) {\n     angular.forEach(tree.children, function(child) {\n       var describeContext = $('<describe></describe>');\n       describeContext.attr('id', child.id);\n       describeContext.attr('name', child.name);\n       context.append(describeContext);\n       serializeXml(describeContext, child);\n     });\n     var its = $('<its></its>');\n     context.append(its);\n     angular.forEach(tree.specs, function(spec) {\n       var it = $('<it></it>');\n       it.attr('id', spec.id);\n       it.attr('name', spec.name);\n       it.attr('duration', spec.duration);\n       it.attr('status', spec.status);\n       its.append(it);\n       angular.forEach(spec.steps, function(step) {\n         var stepContext = $('<step></step>');\n         stepContext.attr('name', step.name);\n         stepContext.attr('duration', step.duration);\n         stepContext.attr('status', step.status);\n         it.append(stepContext);\n         if (step.error) {\n           var error = $('<error></error>');\n           stepContext.append(error);\n           error.text(formatException(stepContext.error));\n         }\n       });\n     });\n   }\n});\n\n/**\n * Creates a global value $result with the result of the runner.\n */\nangular.scenario.output('object', function(context, runner, model) {\n  runner.$window.$result = model.value;\n});\nbindJQuery();\npublishExternalAPI(angular);\n\nvar $runner = new angular.scenario.Runner(window),\n    scripts = document.getElementsByTagName('script'),\n    script = scripts[scripts.length - 1],\n    config = {};\n\nangular.forEach(script.attributes, function(attr) {\n  var match = attr.name.match(/ng[:\\-](.*)/);\n  if (match) {\n    config[match[1]] = attr.value || true;\n  }\n});\n\nif (config.autotest) {\n  JQLite(document).ready(function() {\n    angular.scenario.setUpAndRun(config);\n  });\n}\n})(window, document);\n\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n\\n[ng\\\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\\n.ng-cloak, .x-ng-cloak {\\n  display: none;\\n}\\n\\nng\\\\:form {\\n  display: block;\\n}\\n</style>');\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n/* CSS Document */\\n\\n/** Structure */\\nbody {\\n  font-family: Arial, sans-serif;\\n  margin: 0;\\n  font-size: 14px;\\n}\\n\\n#system-error {\\n  font-size: 1.5em;\\n  text-align: center;\\n}\\n\\n#json, #xml {\\n  display: none;\\n}\\n\\n#header {\\n  position: fixed;\\n  width: 100%;\\n}\\n\\n#specs {\\n  padding-top: 50px;\\n}\\n\\n#header .angular {\\n  font-family: Courier New, monospace;\\n  font-weight: bold;\\n}\\n\\n#header h1 {\\n  font-weight: normal;\\n  float: left;\\n  font-size: 30px;\\n  line-height: 30px;\\n  margin: 0;\\n  padding: 10px 10px;\\n  height: 30px;\\n}\\n\\n#application h2,\\n#specs h2 {\\n  margin: 0;\\n  padding: 0.5em;\\n  font-size: 1.1em;\\n}\\n\\n#status-legend {\\n  margin-top: 10px;\\n  margin-right: 10px;\\n}\\n\\n#header,\\n#application,\\n.test-info,\\n.test-actions li {\\n  overflow: hidden;\\n}\\n\\n#application {\\n  margin: 10px;\\n}\\n\\n#application iframe {\\n  width: 100%;\\n  height: 758px;\\n}\\n\\n#application .popout {\\n  float: right;\\n}\\n\\n#application iframe {\\n  border: none;\\n}\\n\\n.tests li,\\n.test-actions li,\\n.test-it li,\\n.test-it ol,\\n.status-display {\\n  list-style-type: none;\\n}\\n\\n.tests,\\n.test-it ol,\\n.status-display {\\n  margin: 0;\\n  padding: 0;\\n}\\n\\n.test-info {\\n  margin-left: 1em;\\n  margin-top: 0.5em;\\n  border-radius: 8px 0 0 8px;\\n  -webkit-border-radius: 8px 0 0 8px;\\n  -moz-border-radius: 8px 0 0 8px;\\n  cursor: pointer;\\n}\\n\\n.test-info:hover .test-name {\\n  text-decoration: underline;\\n}\\n\\n.test-info .closed:before {\\n  content: \\'\\\\25b8\\\\00A0\\';\\n}\\n\\n.test-info .open:before {\\n  content: \\'\\\\25be\\\\00A0\\';\\n  font-weight: bold;\\n}\\n\\n.test-it ol {\\n  margin-left: 2.5em;\\n}\\n\\n.status-display,\\n.status-display li {\\n  float: right;\\n}\\n\\n.status-display li {\\n  padding: 5px 10px;\\n}\\n\\n.timer-result,\\n.test-title {\\n  display: inline-block;\\n  margin: 0;\\n  padding: 4px;\\n}\\n\\n.test-actions .test-title,\\n.test-actions .test-result {\\n  display: table-cell;\\n  padding-left: 0.5em;\\n  padding-right: 0.5em;\\n}\\n\\n.test-actions {\\n  display: table;\\n}\\n\\n.test-actions li {\\n  display: table-row;\\n}\\n\\n.timer-result {\\n  width: 4em;\\n  padding: 0 10px;\\n  text-align: right;\\n  font-family: monospace;\\n}\\n\\n.test-it pre,\\n.test-actions pre {\\n  clear: left;\\n  color: black;\\n  margin-left: 6em;\\n}\\n\\n.test-describe {\\n  padding-bottom: 0.5em;\\n}\\n\\n.test-describe .test-describe {\\n  margin: 5px 5px 10px 2em;\\n}\\n\\n.test-actions .status-pending .test-title:before {\\n  content: \\'\\\\00bb\\\\00A0\\';\\n}\\n\\n.scrollpane {\\n   max-height: 20em;\\n   overflow: auto;\\n}\\n\\n/** Colors */\\n\\n#header {\\n  background-color: #F2C200;\\n}\\n\\n#specs h2 {\\n  border-top: 2px solid #BABAD1;\\n}\\n\\n#specs h2,\\n#application h2 {\\n  background-color: #efefef;\\n}\\n\\n#application {\\n  border: 1px solid #BABAD1;\\n}\\n\\n.test-describe .test-describe {\\n  border-left: 1px solid #BABAD1;\\n  border-right: 1px solid #BABAD1;\\n  border-bottom: 1px solid #BABAD1;\\n}\\n\\n.status-display {\\n  border: 1px solid #777;\\n}\\n\\n.status-display .status-pending,\\n.status-pending .test-info {\\n  background-color: #F9EEBC;\\n}\\n\\n.status-display .status-success,\\n.status-success .test-info {\\n  background-color: #B1D7A1;\\n}\\n\\n.status-display .status-failure,\\n.status-failure .test-info {\\n  background-color: #FF8286;\\n}\\n\\n.status-display .status-error,\\n.status-error .test-info {\\n  background-color: black;\\n  color: white;\\n}\\n\\n.test-actions .status-success .test-title {\\n  color: #30B30A;\\n}\\n\\n.test-actions .status-failure .test-title {\\n  color: #DF0000;\\n}\\n\\n.test-actions .status-error .test-title {\\n  color: black;\\n}\\n\\n.test-actions .timer-result {\\n  color: #888;\\n}\\n</style>');"
  },
  {
    "path": "chapter3/recipe3/test/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter3/recipe4/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter3/recipe4/index.html",
    "content": "<html>\n  <head>\n    <script src=\"http://code.jquery.com/jquery.min.js\"></script>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <my-widget>\n      <p>This is my paragraph text.</p>\n    </my-widget>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter3/recipe4/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter3/recipe4/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.directive(\"myWidget\", function() {\n  return {\n    restrict: \"E\",\n    transclude: true,\n    template: \"<div ng-transclude><h3>Heading</h3></div>\"\n  };\n});"
  },
  {
    "path": "chapter3/recipe5/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter3/recipe5/index.html",
    "content": "<html>\n  <head>\n    <script src=\"http://code.jquery.com/jquery.min.js\"></script>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <div my-widget=\"Hello World\"></div>\n\n    <my-widget-bi text=\"Hello World\"></my-widget-bi>\n\n    <my-widget-expr fn=\"count = count + 1\"></my-widget-expr>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter3/recipe5/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter3/recipe5/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.directive(\"myWidget\", function() {\n  var linkFunction = function(scope, element, attributes) {\n    scope.text = attributes[\"myWidget\"];\n  };\n\n  return {\n    restrict: \"A\",\n    template: \"<p>{{text}}</p>\",\n    link: linkFunction,\n    scope: {}\n  };\n});\n\napp.directive(\"myWidgetBi\", function() {\n  return {\n    restrict: \"E\",\n    template: \"<p>{{text}}</p>\",\n    scope: {\n      text: \"@text\"\n    }\n  };\n});\n\napp.directive(\"myWidgetExpr\", function() {\n  var linkFunction = function(scope, element, attributes) {\n    scope.text = scope.fn({ count: 5 });\n  };\n\n  return {\n    restrict: \"E\",\n    template: \"<p>{{text}}</p>\",\n    link: linkFunction,\n    scope: {\n      fn: \"&fn\"\n    }\n  };\n});"
  },
  {
    "path": "chapter3/recipe6/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter3/recipe6/index.html",
    "content": "<html>\n  <head>\n    <script src=\"http://code.jquery.com/jquery.min.js\"></script>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <repeat-ntimes repeat=\"10\">\n      <h1>Header 1</h1>\n      <p>This is the paragraph.</p>\n    </repeat-n-times>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter3/recipe6/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter3/recipe6/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.directive(\"repeatNtimes\", function() {\n  return {\n    restrict: \"E\",\n    compile: function(tElement, attrs) {\n      var content = tElement.children();\n      for (var i=1; i<attrs.repeat; i++) {\n        tElement.append(content.clone());\n      }\n\n      return function (scope, element, attrs) {\n        element.on(\"click\", \"h1\", function() {\n          $(this).css({ \"background-color\": \"red\" });\n        });\n      };\n    }\n  };\n});"
  },
  {
    "path": "chapter3/recipe7/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter3/recipe7/index.html",
    "content": "<html>\n  <head>\n    <script src=\"http://code.jquery.com/jquery.min.js\"></script>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <basket apple orange>Roll over me and check the console!</basket>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter3/recipe7/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter3/recipe7/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.directive(\"basket\", function() {\n  return {\n    restrict: \"E\",\n    controller: function($scope, $element, $attrs) {\n      $scope.content = [];\n\n      this.addApple = function() {\n        $scope.content.push(\"apple\");\n      };\n\n      this.addOrange = function() {\n        $scope.content.push(\"orange\");\n      };\n    },\n    link: function(scope, element) {\n      element.bind(\"mouseenter\", function() {\n        console.log(scope.content);\n      });\n    }\n  };\n});\n\napp.directive(\"apple\", function() {\n  return {\n    require: \"basket\",\n    link: function(scope, element, attrs, basketCtrl) {\n      basketCtrl.addApple();\n    }\n  };\n});\n\napp.directive(\"orange\", function() {\n  return {\n    require: \"basket\",\n    link: function(scope, element, attrs, basketCtrl) {\n      basketCtrl.addOrange();\n    }\n  };\n});"
  },
  {
    "path": "chapter3/recipe8/README.md",
    "content": "# angular-seed — the seed for AngularJS apps\n\nThis project is an application skeleton for a typical [AngularJS](http://angularjs.org/) web app.\nYou can use it to quickly bootstrap your angular webapp projects and dev environment for these\nprojects.\n\nThe seed contains AngularJS libraries, test libraries and a bunch of scripts all preconfigured for\ninstant web development gratification. Just clone the repo (or download the zip/tarball), start up\nour (or yours) webserver and you are ready to develop and test your application.\n\nThe seed app doesn't do much, just shows how to wire two controllers and views together. You can\ncheck it out by opening app/index.html in your browser (might not work file `file://` scheme in\ncertain browsers, see note below).\n\n_Note: While angular is client-side-only technology and it's possible to create angular webapps that\ndon't require a backend server at all, we recommend hosting the project files using a local\nwebserver during development to avoid issues with security restrictions (sandbox) in browsers. The\nsandbox implementation varies between browsers, but quite often prevents things like cookies, xhr,\netc to function properly when an html page is opened via `file://` scheme instead of `http://`._\n\n\n## How to use angular-seed\n\nClone the angular-seed repository and start hacking...\n\n\n### Running the app during development\n\nYou can pick one of these options:\n\n* serve this repository with your webserver\n* install node.js and run `scripts/web-server.js`\n\nThen navigate your browser to `http://localhost:<port>/app/index.html` to see the app running in\nyour browser.\n\n\n### Running the app in production\n\nThis really depends on how complex is your app and the overall infrastructure of your system, but\nthe general rule is that all you need in production are all the files under the `app/` directory.\nEverything else should be omitted.\n\nAngular apps are really just a bunch of static html, css and js files that just need to be hosted\nsomewhere, where they can be accessed by browsers.\n\nIf your Angular app is talking to the backend server via xhr or other means, you need to figure\nout what is the best way to host the static files to comply with the same origin policy if\napplicable. Usually this is done by hosting the files by the backend server or through\nreverse-proxying the backend server(s) and a webserver(s).\n\n\n### Running unit tests\n\nWe recommend using [jasmine](http://pivotal.github.com/jasmine/) and\n[Testacular](http://vojtajina.github.com/testacular/) for your unit tests/specs, but you are free\nto use whatever works for you.\n\nRequires [node.js](http://nodejs.org/), Testacular (`sudo npm install -g testacular`) and a local\nor remote browser.\n\n* start `scripts/test.sh` (on windows: `scripts\\test.bat`)\n  * a browser will start and connect to the Testacular server (Chrome is default browser, others can be captured by loading the same url as the one in Chrome or by changing the `config/testacular.conf.js` file)\n* to run or re-run tests just change any of your source or test javascript files\n\n\n### End to end testing\n\nAngular ships with a baked-in end-to-end test runner that understands angular, your app and allows\nyou to write your tests with jasmine-like BDD syntax.\n\nRequires a webserver, node.js + `./scripts/web-server.js` or your backend server that hosts the angular static files.\n\nCheck out the\n[end-to-end runner's documentation](http://docs.angularjs.org/guide/dev_guide.e2e-testing) for more\ninfo.\n\n* create your end-to-end tests in `test/e2e/scenarios.js`\n* serve your project directory with your http/backend server or node.js + `scripts/web-server.js`\n* to run do one of:\n  * open `http://localhost:port/test/e2e/runner.html` in your browser\n  * run the tests from console with [Testacular](vojtajina.github.com/testacular) via\n    `scripts/e2e-test.sh` or `script/e2e-test.bat`\n\n\n### Receiving updates from upstream\n\nWhen we upgrade angular-seed's repo with newer angular or testing library code, you can just\nfetch the changes and merge them into your project with git.\n\n\n## Directory Layout\n\n    app/                --> all of the files to be used in production\n      css/              --> css files\n        app.css         --> default stylesheet\n      img/              --> image files\n      index.html        --> app layout file (the main html template file of the app)\n      index-async.html  --> just like index.html, but loads js files asynchronously\n      js/               --> javascript files\n        app.js          --> application\n        controllers.js  --> application controllers\n        directives.js   --> application directives\n        filters.js      --> custom angular filters\n        services.js     --> custom angular services\n      lib/              --> angular and 3rd party javascript libraries\n        angular/\n          angular.js        --> the latest angular js\n          angular.min.js    --> the latest minified angular js\n          angular-*.js      --> angular add-on modules\n          version.txt       --> version number\n      partials/             --> angular view partials (partial html templates)\n        partial1.html\n        partial2.html\n\n    config/testacular.conf.js        --> config file for running unit tests with Testacular\n    config/testacular-e2e.conf.js    --> config file for running e2e tests with Testacular\n\n    scripts/            --> handy shell/js/ruby scripts\n      e2e-test.sh       --> runs end-to-end tests with Testacular (*nix)\n      e2e-test.bat      --> runs end-to-end tests with Testacular (windows)\n      test.bat          --> autotests unit tests with Testacular (windows)\n      test.sh           --> autotests unit tests with Testacular (*nix)\n      web-server.js     --> simple development webserver based on node.js\n\n    test/               --> test source files and libraries\n      e2e/              -->\n        runner.html     --> end-to-end test runner (open in your browser to run)\n        scenarios.js    --> end-to-end specs\n      lib/\n        angular/                --> angular testing libraries\n          angular-mocks.js      --> mocks that replace certain angular services in tests\n          angular-scenario.js   --> angular's scenario (end-to-end) test runner library\n          version.txt           --> version file\n      unit/                     --> unit level specs/tests\n        controllersSpec.js      --> specs for controllers\n        directivessSpec.js      --> specs for directives\n        filtersSpec.js          --> specs for filters\n        servicesSpec.js         --> specs for services\n\n## Contact\n\nFor more information on AngularJS please check out http://angularjs.org/\n"
  },
  {
    "path": "chapter3/recipe8/app/css/.gitignore",
    "content": ""
  },
  {
    "path": "chapter3/recipe8/app/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter3/recipe8/app/img/.gitignore",
    "content": ""
  },
  {
    "path": "chapter3/recipe8/app/index-async.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <style>\n    [ng-cloak] {\n      display: none;\n    }\n  </style>\n  <script>\n    // include angular loader, which allows the files to load in any order\n    /*\n     AngularJS v1.0.0rc1\n     (c) 2010-2012 AngularJS http://angularjs.org\n     License: MIT\n    */\n    'use strict';(function(i){function d(c,a,e){return c[a]||(c[a]=e())}return d(d(i,\"angular\",Object),\"module\",function(){var c={};return function(a,e,f){e&&c.hasOwnProperty(a)&&(c[a]=null);return d(c,a,function(){function b(a,b,d){return function(){c[d||\"push\"]([a,b,arguments]);return g}}if(!e)throw Error(\"No module: \"+a);var c=[],d=[],h=b(\"$injector\",\"invoke\"),g={_invokeQueue:c,_runBlocks:d,requires:e,name:a,provider:b(\"$provide\",\"provider\"),factory:b(\"$provide\",\"factory\"),service:b(\"$provide\",\"service\"),\n    value:b(\"$provide\",\"value\"),constant:b(\"$provide\",\"constant\",\"unshift\"),filter:b(\"$filterProvider\",\"register\"),directive:b(\"$compileProvider\",\"directive\"),config:h,run:function(a){d.push(a);return this}};f&&h(f);return g})}})})(window);\n\n    // include a third-party async loader library\n    /*!\n     * $script.js v1.3\n     * https://github.com/ded/script.js\n     * Copyright: @ded & @fat - Dustin Diaz, Jacob Thornton 2011\n     * Follow our software http://twitter.com/dedfat\n     * License: MIT\n     */\n    !function(a,b,c){function t(a,c){var e=b.createElement(\"script\"),f=j;e.onload=e.onerror=e[o]=function(){e[m]&&!/^c|loade/.test(e[m])||f||(e.onload=e[o]=null,f=1,c())},e.async=1,e.src=a,d.insertBefore(e,d.firstChild)}function q(a,b){p(a,function(a){return!b(a)})}var d=b.getElementsByTagName(\"head\")[0],e={},f={},g={},h={},i=\"string\",j=!1,k=\"push\",l=\"DOMContentLoaded\",m=\"readyState\",n=\"addEventListener\",o=\"onreadystatechange\",p=function(a,b){for(var c=0,d=a.length;c<d;++c)if(!b(a[c]))return j;return 1};!b[m]&&b[n]&&(b[n](l,function r(){b.removeEventListener(l,r,j),b[m]=\"complete\"},j),b[m]=\"loading\");var s=function(a,b,d){function o(){if(!--m){e[l]=1,j&&j();for(var a in g)p(a.split(\"|\"),n)&&!q(g[a],n)&&(g[a]=[])}}function n(a){return a.call?a():e[a]}a=a[k]?a:[a];var i=b&&b.call,j=i?b:d,l=i?a.join(\"\"):b,m=a.length;c(function(){q(a,function(a){h[a]?(l&&(f[l]=1),o()):(h[a]=1,l&&(f[l]=1),t(s.path?s.path+a+\".js\":a,o))})},0);return s};s.get=t,s.ready=function(a,b,c){a=a[k]?a:[a];var d=[];!q(a,function(a){e[a]||d[k](a)})&&p(a,function(a){return e[a]})?b():!function(a){g[a]=g[a]||[],g[a][k](b),c&&c(d)}(a.join(\"|\"));return s};var u=a.$script;s.noConflict=function(){a.$script=u;return this},typeof module!=\"undefined\"&&module.exports?module.exports=s:a.$script=s}(this,document,setTimeout)\n\n    // load all of the dependencies asynchronously.\n    $script([\n      'lib/angular/angular.js',\n      'js/app.js',\n      'js/services.js',\n      'js/controllers.js',\n      'js/filters.js',\n      'js/directives.js'\n    ], function() {\n      // when all is done, execute bootstrap angular application\n      angular.bootstrap(document, ['myApp']);\n    });\n  </script>\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\">\n</head>\n<body ng-cloak>\n  <ul class=\"menu\">\n    <li><a href=\"#/view1\">view1</a></li>\n    <li><a href=\"#/view2\">view2</a></li>\n  </ul>\n\n  <div ng-view></div>\n\n  <div>Angular seed app: v<span app-version></span></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "chapter3/recipe8/app/index.html",
    "content": "<!doctype html>\n<html lang=\"en\" ng-app=\"MyApp\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/bootstrap.css\"/>\n</head>\n<body>\n  <tabs>\n    <pane title=\"First Tab\">First pane.</pane>\n    <pane title=\"Second Tab\">Second pane.</pane>\n  </tabs>\n\n  <script src=\"lib/jquery.min.js\"></script>\n  <script src=\"lib/angular/angular.js\"></script>\n  <script src=\"js/app.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "chapter3/recipe8/app/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.directive(\"tabs\", function() {\n  return {\n    restrict: \"E\",\n    transclude: true,\n    scope: {},\n    controller: function($scope, $element) {\n      var panes = $scope.panes = [];\n\n      $scope.select = function(pane) {\n        angular.forEach(panes, function(pane) {\n          pane.selected = false;\n        });\n        pane.selected = true;\n        console.log(\"selected pane: \", pane.title);\n      };\n\n      this.addPane = function(pane) {\n        if (!panes.length) $scope.select(pane);\n        panes.push(pane);\n      };\n    },\n    template:\n      '<div class=\"tabbable\">' +\n        '<ul class=\"nav nav-tabs\">' +\n          '<li ng-repeat=\"pane in panes\" ng-class=\"{active:pane.selected}\">'+\n            '<a href=\"\" ng-click=\"select(pane)\">{{pane.title}}</a>' +\n          '</li>' +\n        '</ul>' +\n        '<div class=\"tab-content\" ng-transclude></div>' +\n      '</div>',\n    replace: true\n  };\n});\n\napp.directive(\"pane\", function() {\n  return {\n    require: \"^tabs\",\n    restrict: \"E\",\n    transclude: true,\n    scope: {\n      title: \"@\"\n    },\n    link: function(scope, element, attrs, tabsCtrl) {\n      tabsCtrl.addPane(scope);\n    },\n    template: '<div class=\"tab-pane\" ng-class=\"{active: selected}\" ng-transclude></div>',\n    replace: true\n  };\n});"
  },
  {
    "path": "chapter3/recipe8/app/lib/angular/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngCookies\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookies\n   * @requires $browser\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from\n   * this object, new cookies are created/deleted at the end of current $eval.\n   *\n   * @example\n   */\n   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for(name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            if (angular.isDefined(lastCookies[name])) {\n              cookies[name] = lastCookies[name];\n            } else {\n              delete cookies[name];\n            }\n          } else if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated){\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   * @example\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#get\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          return angular.fromJson($cookies[key]);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#put\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#remove\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter3/recipe8/app/lib/angular/angular-loader.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n\n(\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n'use strict';\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n)(window);\n\n/**\n * Closure compiler type information\n *\n * @typedef { {\n *   requires: !Array.<string>,\n *   invokeQueue: !Array.<Array.<*>>,\n *\n *   service: function(string, Function):angular.Module,\n *   factory: function(string, Function):angular.Module,\n *   value: function(string, *):angular.Module,\n *\n *   filter: function(string, Function):angular.Module,\n *\n *   init: function(Function):angular.Module\n * } }\n */\nangular.Module;\n\n"
  },
  {
    "path": "chapter3/recipe8/app/lib/angular/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g. \n *   `http://example.com:8080/api`), you'll need to escape the colon character before the port\n *   number, like this: `$resource('http://example.com\\\\:8080/api')`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` – {string} – The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` – {object=} – Optional set of pre-bound parameters for this action.\n *   - isArray – {boolean=} – If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n     * encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace((pctEncodeSpaces ? null : /%20/g), '+');\n    }\n\n    function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        action.method = angular.uppercase(action.method);\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter3/recipe8/app/lib/angular/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             '<p style=\"color:blue\">an html\\n' +\n             '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n             'snippet</p>';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n          Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n           <table>\n             <tr>\n               <td>Filter</td>\n               <td>Source</td>\n               <td>Rendered</td>\n             </tr>\n             <tr id=\"html-filter\">\n               <td>html filter</td>\n               <td>\n                 <pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre>\n               </td>\n               <td>\n                 <div ng-bind-html=\"snippet\"></div>\n               </td>\n             </tr>\n             <tr id=\"escaped-html\">\n               <td>no filter</td>\n               <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind=\"snippet\"></div></td>\n             </tr>\n             <tr id=\"html-unsafe-filter\">\n               <td>unsafe html filter</td>\n               <td><pre>&lt;div ng-bind-html-unsafe=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind-html-unsafe=\"snippet\"></div></td>\n             </tr>\n           </table>\n         </div>\n     </doc:source>\n     <doc:scenario>\n       it('should sanitize the html snippet ', function() {\n         expect(using('#html-filter').element('div').html()).\n           toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n       });\n\n       it('should escape snippet without any filter', function() {\n         expect(using('#escaped-html').element('div').html()).\n           toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n                \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n                \"snippet&lt;/p&gt;\");\n       });\n\n       it('should inline raw snippet if filtered as unsafe', function() {\n         expect(using('#html-unsafe-filter').element(\"div\").html()).\n           toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n                \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n                \"snippet</p>\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new <b>text</b>');\n         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');\n         expect(using('#escaped-html').element('div').html()).toBe(\"new &lt;b&gt;text&lt;/b&gt;\");\n         expect(using('#html-unsafe-filter').binding(\"snippet\")).toBe('new <b>text</b>');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar $sanitize = function(html) {\n  var buf = [];\n    htmlParser(html, htmlSanitizeWriter(buf));\n    return buf.join('');\n};\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP = /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  URI_REGEXP = /^((ftp|https?):\\/\\/|mailto:|#)/,\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g; // Match everything outside of normal chars and \" (quote character)\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,aside,\" +\n        \"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,\" +\n        \"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,bdi,bdo,\" +\n        \"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,\" +\n        \"span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        index = html.indexOf(\"-->\");\n\n        if ( index >= 0 ) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'), function(all, text){\n        text = text.\n          replace(COMMENT_REGEXP, \"$1\").\n          replace(CDATA_REGEXP, \"$1\");\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n\n        return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw \"Parse Error: \" + html;\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {\n      var value = doubleQuotedValue\n        || singleQoutedValue\n        || unqoutedValue\n        || '';\n\n      attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nvar hiddenPre=document.createElement(\"pre\");\nfunction decodeEntities(value) {\n  hiddenPre.innerHTML=value.replace(/</g,\"&lt;\");\n  return hiddenPre.innerText || hiddenPre.textContent || '';\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] == true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] == true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).value('$sanitize', $sanitize);\n\n/**\n * @ngdoc directive\n * @name ngSanitize.directive:ngBindHtml\n *\n * @description\n * Creates a binding that will sanitize the result of evaluating the `expression` with the\n * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n */\nangular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);\n    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {\n      value = $sanitize(value);\n      element.html(value || '');\n    });\n  };\n}]);\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n *   plain email address links.\n *\n * @param {string} text Input text.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should linkify the snippet with urls', function() {\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('Pretty text with some links:&#10;' +\n                '<a href=\"http://angularjs.org/\">http://angularjs.org/</a>,&#10;' +\n                '<a href=\"mailto:us@somewhere.org\">us@somewhere.org</a>,&#10;' +\n                '<a href=\"mailto:another@somewhere.org\">another@somewhere.org</a>,&#10;' +\n                'and one more: <a href=\"ftp://127.0.0.1/\">ftp://127.0.0.1/</a>.');\n       });\n\n       it ('should not linkify snippet without the linky filter', function() {\n         expect(using('#escaped-html').binding('snippet')).\n           toBe(\"Pretty text with some links:\\n\" +\n                \"http://angularjs.org/,\\n\" +\n                \"mailto:us@somewhere.org,\\n\" +\n                \"another@somewhere.org,\\n\" +\n                \"and one more: ftp://127.0.0.1/.\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new http://link.');\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('new <a href=\"http://link\">http://link</a>.');\n         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', function() {\n  var LINKY_URL_REGEXP = /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s\\.\\;\\,\\(\\)\\{\\}\\<\\>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    // TODO(vojta): use $sanitize instead\n    var writer = htmlSanitizeWriter(html);\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      writer.chars(raw.substr(0, i));\n      writer.start('a', {href:url});\n      writer.chars(match[0].replace(MAILTO_REGEXP, ''));\n      writer.end('a');\n      raw = raw.substring(i + match[0].length);\n    }\n    writer.chars(raw);\n    return html.join('');\n  };\n});\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter3/recipe8/app/lib/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter3/recipe8/app/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter3/recipe8/app/partials/.gitignore",
    "content": ""
  },
  {
    "path": "chapter3/recipe8/app/partials/partial1.html",
    "content": "<p>This is the partial for view 1.</p>\n"
  },
  {
    "path": "chapter3/recipe8/app/partials/partial2.html",
    "content": "<p>This is the partial for view 2.</p>\n<p>\n  Showing of 'interpolate' filter:\n  {{ 'Current version is v%VERSION%.' | interpolate }}\n</p>\n"
  },
  {
    "path": "chapter3/recipe8/config/testacular-e2e.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  ANGULAR_SCENARIO,\n  ANGULAR_SCENARIO_ADAPTER,\n  'test/e2e/**/*.js'\n];\n\nautoWatch = false;\n\nbrowsers = ['Chrome'];\n\nsingleRun = true;\n\nproxies = {\n  '/': 'http://localhost:8000/'\n};\n\njunitReporter = {\n  outputFile: 'test_out/e2e.xml',\n  suite: 'e2e'\n};\n"
  },
  {
    "path": "chapter3/recipe8/config/testacular.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  JASMINE,\n  JASMINE_ADAPTER,\n  'app/lib/jquery.min.js',\n  'app/lib/angular/angular.js',\n  'app/lib/angular/angular-*.js',\n  'test/lib/angular/angular-mocks.js',\n  'test/lib/jasmine-jquery.js',\n  'app/js/**/*.js',\n  'test/unit/**/*.js'\n];\n\nautoWatch = true;\n\nbrowsers = ['Chrome'];\n\njunitReporter = {\n  outputFile: 'test_out/unit.xml',\n  suite: 'unit'\n};\n"
  },
  {
    "path": "chapter3/recipe8/logs/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "chapter3/recipe8/scripts/e2e-test.bat",
    "content": "@echo off\n\nREM Windows script for running e2e tests\nREM You have to run server and capture some browser first\nREM\nREM Requirements:\nREM - NodeJS (http://nodejs.org/)\nREM - Testacular (npm install -g testacular)\n\nset BASE_DIR=%~dp0\ntestacular start \"%BASE_DIR%\\..\\config\\testacular-e2e.conf.js\" %*\n"
  },
  {
    "path": "chapter3/recipe8/scripts/e2e-test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular-e2e.conf.js $*\n"
  },
  {
    "path": "chapter3/recipe8/scripts/test.bat",
    "content": "@echo off\r\n\r\nREM Windows script for running unit tests\r\nREM You have to run server and capture some browser first\r\nREM\r\nREM Requirements:\r\nREM - NodeJS (http://nodejs.org/)\r\nREM - Testacular (npm install -g testacular)\r\n\r\nset BASE_DIR=%~dp0\r\ntestacular start \"%BASE_DIR%\\..\\config\\testacular.conf.js\" %*\r\n"
  },
  {
    "path": "chapter3/recipe8/scripts/test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular.conf.js $*\n"
  },
  {
    "path": "chapter3/recipe8/scripts/watchr.rb",
    "content": "#!/usr/bin/env watchr\n\n# config file for watchr http://github.com/mynyml/watchr\n# install: gem install watchr\n# run: watch watchr.rb\n# note: make sure that you have jstd server running (server.sh) and a browser captured\n\nlog_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log')\n\n`cd ..`\n`touch #{log_file}`\n\nputs \"String watchr... log file: #{log_file}\"\n\nwatch( '(app/js|test/unit)' )  do\n  `echo \"\\n\\ntest run started @ \\`date\\`\" > #{log_file}`\n  `scripts/test.sh &> #{log_file}`\nend\n\n"
  },
  {
    "path": "chapter3/recipe8/scripts/web-server.js",
    "content": "#!/usr/bin/env node\n\nvar util = require('util'),\n    http = require('http'),\n    fs = require('fs'),\n    url = require('url'),\n    events = require('events');\n\nvar DEFAULT_PORT = 8000;\n\nfunction main(argv) {\n  new HttpServer({\n    'GET': createServlet(StaticServlet),\n    'HEAD': createServlet(StaticServlet)\n  }).start(Number(argv[2]) || DEFAULT_PORT);\n}\n\nfunction escapeHtml(value) {\n  return value.toString().\n    replace('<', '&lt;').\n    replace('>', '&gt;').\n    replace('\"', '&quot;');\n}\n\nfunction createServlet(Class) {\n  var servlet = new Class();\n  return servlet.handleRequest.bind(servlet);\n}\n\n/**\n * An Http server implementation that uses a map of methods to decide\n * action routing.\n *\n * @param {Object} Map of method => Handler function\n */\nfunction HttpServer(handlers) {\n  this.handlers = handlers;\n  this.server = http.createServer(this.handleRequest_.bind(this));\n}\n\nHttpServer.prototype.start = function(port) {\n  this.port = port;\n  this.server.listen(port);\n  util.puts('Http Server running at http://localhost:' + port + '/');\n};\n\nHttpServer.prototype.parseUrl_ = function(urlString) {\n  var parsed = url.parse(urlString);\n  parsed.pathname = url.resolve('/', parsed.pathname);\n  return url.parse(url.format(parsed), true);\n};\n\nHttpServer.prototype.handleRequest_ = function(req, res) {\n  var logEntry = req.method + ' ' + req.url;\n  if (req.headers['user-agent']) {\n    logEntry += ' ' + req.headers['user-agent'];\n  }\n  util.puts(logEntry);\n  req.url = this.parseUrl_(req.url);\n  var handler = this.handlers[req.method];\n  if (!handler) {\n    res.writeHead(501);\n    res.end();\n  } else {\n    handler.call(this, req, res);\n  }\n};\n\n/**\n * Handles static content.\n */\nfunction StaticServlet() {}\n\nStaticServlet.MimeMap = {\n  'txt': 'text/plain',\n  'html': 'text/html',\n  'css': 'text/css',\n  'xml': 'application/xml',\n  'json': 'application/json',\n  'js': 'application/javascript',\n  'jpg': 'image/jpeg',\n  'jpeg': 'image/jpeg',\n  'gif': 'image/gif',\n  'png': 'image/png',\n  'svg': 'image/svg+xml'\n};\n\nStaticServlet.prototype.handleRequest = function(req, res) {\n  var self = this;\n  var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){\n    return String.fromCharCode(parseInt(hex, 16));\n  });\n  var parts = path.split('/');\n  if (parts[parts.length-1].charAt(0) === '.')\n    return self.sendForbidden_(req, res, path);\n  fs.stat(path, function(err, stat) {\n    if (err)\n      return self.sendMissing_(req, res, path);\n    if (stat.isDirectory())\n      return self.sendDirectory_(req, res, path);\n    return self.sendFile_(req, res, path);\n  });\n}\n\nStaticServlet.prototype.sendError_ = function(req, res, error) {\n  res.writeHead(500, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>Internal Server Error</title>\\n');\n  res.write('<h1>Internal Server Error</h1>');\n  res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');\n  util.puts('500 Internal Server Error');\n  util.puts(util.inspect(error));\n};\n\nStaticServlet.prototype.sendMissing_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(404, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>404 Not Found</title>\\n');\n  res.write('<h1>Not Found</h1>');\n  res.write(\n    '<p>The requested URL ' +\n    escapeHtml(path) +\n    ' was not found on this server.</p>'\n  );\n  res.end();\n  util.puts('404 Not Found: ' + path);\n};\n\nStaticServlet.prototype.sendForbidden_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(403, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>403 Forbidden</title>\\n');\n  res.write('<h1>Forbidden</h1>');\n  res.write(\n    '<p>You do not have permission to access ' +\n    escapeHtml(path) + ' on this server.</p>'\n  );\n  res.end();\n  util.puts('403 Forbidden: ' + path);\n};\n\nStaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {\n  res.writeHead(301, {\n      'Content-Type': 'text/html',\n      'Location': redirectUrl\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>301 Moved Permanently</title>\\n');\n  res.write('<h1>Moved Permanently</h1>');\n  res.write(\n    '<p>The document has moved <a href=\"' +\n    redirectUrl +\n    '\">here</a>.</p>'\n  );\n  res.end();\n  util.puts('301 Moved Permanently: ' + redirectUrl);\n};\n\nStaticServlet.prototype.sendFile_ = function(req, res, path) {\n  var self = this;\n  var file = fs.createReadStream(path);\n  res.writeHead(200, {\n    'Content-Type': StaticServlet.\n      MimeMap[path.split('.').pop()] || 'text/plain'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n  } else {\n    file.on('data', res.write.bind(res));\n    file.on('close', function() {\n      res.end();\n    });\n    file.on('error', function(error) {\n      self.sendError_(req, res, error);\n    });\n  }\n};\n\nStaticServlet.prototype.sendDirectory_ = function(req, res, path) {\n  var self = this;\n  if (path.match(/[^\\/]$/)) {\n    req.url.pathname += '/';\n    var redirectUrl = url.format(url.parse(url.format(req.url)));\n    return self.sendRedirect_(req, res, redirectUrl);\n  }\n  fs.readdir(path, function(err, files) {\n    if (err)\n      return self.sendError_(req, res, error);\n\n    if (!files.length)\n      return self.writeDirectoryIndex_(req, res, path, []);\n\n    var remaining = files.length;\n    files.forEach(function(fileName, index) {\n      fs.stat(path + '/' + fileName, function(err, stat) {\n        if (err)\n          return self.sendError_(req, res, err);\n        if (stat.isDirectory()) {\n          files[index] = fileName + '/';\n        }\n        if (!(--remaining))\n          return self.writeDirectoryIndex_(req, res, path, files);\n      });\n    });\n  });\n};\n\nStaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {\n  path = path.substring(1);\n  res.writeHead(200, {\n    'Content-Type': 'text/html'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n    return;\n  }\n  res.write('<!doctype html>\\n');\n  res.write('<title>' + escapeHtml(path) + '</title>\\n');\n  res.write('<style>\\n');\n  res.write('  ol { list-style-type: none; font-size: 1.2em; }\\n');\n  res.write('</style>\\n');\n  res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');\n  res.write('<ol>');\n  files.forEach(function(fileName) {\n    if (fileName.charAt(0) !== '.') {\n      res.write('<li><a href=\"' +\n        escapeHtml(fileName) + '\">' +\n        escapeHtml(fileName) + '</a></li>');\n    }\n  });\n  res.write('</ol>');\n  res.end();\n};\n\n// Must be last,\nmain(process.argv);\n"
  },
  {
    "path": "chapter3/recipe8/test/e2e/runner.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <title>End2end Test Runner</title>\n    <script src=\"../lib/angular/angular-scenario.js\" ng-autotest></script>\n    <script src=\"scenarios.js\"></script>\n  </head>\n  <body>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter3/recipe8/test/e2e/scenarios.js",
    "content": "'use strict';\n\n/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */\n\ndescribe('my app', function() {\n\n  beforeEach(function() {\n    browser().navigateTo('../../app/index.html');\n  });\n\n\n  it('should automatically redirect to /view1 when location hash/fragment is empty', function() {\n    expect(browser().location().url()).toBe(\"/view1\");\n  });\n\n\n  describe('view1', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view1');\n    });\n\n\n    it('should render view1 when user navigates to /view1', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 1/);\n    });\n\n  });\n\n\n  describe('view2', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view2');\n    });\n\n\n    it('should render view2 when user navigates to /view2', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 2/);\n    });\n\n  });\n});\n"
  },
  {
    "path": "chapter3/recipe8/test/lib/angular/angular-mocks.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n *\n * TODO(vojta): wrap whole file into closure during build\n */\n\n/**\n * @ngdoc overview\n * @name angular.mock\n * @description\n *\n * Namespace from 'angular-mocks.js' which contains testing related code.\n */\nangular.mock = {};\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ngMock.$browser\n *\n * @description\n * This service is a mock implementation of {@link ng.$browser}. It provides fake\n * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,\n * cookies, etc...\n *\n * The api of this service is the same as that of the real {@link ng.$browser $browser}, except\n * that there are several helper methods available which can be used in tests.\n */\nangular.mock.$BrowserProvider = function() {\n  this.$get = function(){\n    return new angular.mock.$Browser();\n  };\n};\n\nangular.mock.$Browser = function() {\n  var self = this;\n\n  this.isMock = true;\n  self.$$url = \"http://server/\";\n  self.$$lastUrl = self.$$url; // used by url polling fn\n  self.pollFns = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = angular.noop;\n  self.$$incOutstandingRequestCount = angular.noop;\n\n\n  // register url polling fn\n\n  self.onUrlChange = function(listener) {\n    self.pollFns.push(\n      function() {\n        if (self.$$lastUrl != self.$$url) {\n          self.$$lastUrl = self.$$url;\n          listener(self.$$url);\n        }\n      }\n    );\n\n    return listener;\n  };\n\n  self.cookieHash = {};\n  self.lastCookieHash = {};\n  self.deferredFns = [];\n  self.deferredNextId = 0;\n\n  self.defer = function(fn, delay) {\n    delay = delay || 0;\n    self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});\n    self.deferredFns.sort(function(a,b){ return a.time - b.time;});\n    return self.deferredNextId++;\n  };\n\n\n  self.defer.now = 0;\n\n\n  self.defer.cancel = function(deferId) {\n    var fnIndex;\n\n    angular.forEach(self.deferredFns, function(fn, index) {\n      if (fn.id === deferId) fnIndex = index;\n    });\n\n    if (fnIndex !== undefined) {\n      self.deferredFns.splice(fnIndex, 1);\n      return true;\n    }\n\n    return false;\n  };\n\n\n  /**\n   * @name ngMock.$browser#defer.flush\n   * @methodOf ngMock.$browser\n   *\n   * @description\n   * Flushes all pending requests and executes the defer callbacks.\n   *\n   * @param {number=} number of milliseconds to flush. See {@link #defer.now}\n   */\n  self.defer.flush = function(delay) {\n    if (angular.isDefined(delay)) {\n      self.defer.now += delay;\n    } else {\n      if (self.deferredFns.length) {\n        self.defer.now = self.deferredFns[self.deferredFns.length-1].time;\n      } else {\n        throw Error('No deferred tasks to be flushed');\n      }\n    }\n\n    while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {\n      self.deferredFns.shift().fn();\n    }\n  };\n  /**\n   * @name ngMock.$browser#defer.now\n   * @propertyOf ngMock.$browser\n   *\n   * @description\n   * Current milliseconds mock time.\n   */\n\n  self.$$baseHref = '';\n  self.baseHref = function() {\n    return this.$$baseHref;\n  };\n};\nangular.mock.$Browser.prototype = {\n\n/**\n  * @name ngMock.$browser#poll\n  * @methodOf ngMock.$browser\n  *\n  * @description\n  * run all fns in pollFns\n  */\n  poll: function poll() {\n    angular.forEach(this.pollFns, function(pollFn){\n      pollFn();\n    });\n  },\n\n  addPollFn: function(pollFn) {\n    this.pollFns.push(pollFn);\n    return pollFn;\n  },\n\n  url: function(url, replace) {\n    if (url) {\n      this.$$url = url;\n      return this;\n    }\n\n    return this.$$url;\n  },\n\n  cookies:  function(name, value) {\n    if (name) {\n      if (value == undefined) {\n        delete this.cookieHash[name];\n      } else {\n        if (angular.isString(value) &&       //strings only\n            value.length <= 4096) {          //strict cookie storage limits\n          this.cookieHash[name] = value;\n        }\n      }\n    } else {\n      if (!angular.equals(this.cookieHash, this.lastCookieHash)) {\n        this.lastCookieHash = angular.copy(this.cookieHash);\n        this.cookieHash = angular.copy(this.cookieHash);\n      }\n      return this.cookieHash;\n    }\n  },\n\n  notifyWhenNoOutstandingRequests: function(fn) {\n    fn();\n  }\n};\n\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandlerProvider\n *\n * @description\n * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed\n * into the `$exceptionHandler`.\n */\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandler\n *\n * @description\n * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed\n * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration\n * information.\n *\n *\n * <pre>\n *   describe('$exceptionHandlerProvider', function() {\n *\n *     it('should capture log messages and exceptions', function() {\n *\n *       module(function($exceptionHandlerProvider) {\n *         $exceptionHandlerProvider.mode('log');\n *       });\n *\n *       inject(function($log, $exceptionHandler, $timeout) {\n *         $timeout(function() { $log.log(1); });\n *         $timeout(function() { $log.log(2); throw 'banana peel'; });\n *         $timeout(function() { $log.log(3); });\n *         expect($exceptionHandler.errors).toEqual([]);\n *         expect($log.assertEmpty());\n *         $timeout.flush();\n *         expect($exceptionHandler.errors).toEqual(['banana peel']);\n *         expect($log.log.logs).toEqual([[1], [2], [3]]);\n *       });\n *     });\n *   });\n * </pre>\n */\n\nangular.mock.$ExceptionHandlerProvider = function() {\n  var handler;\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$exceptionHandlerProvider#mode\n   * @methodOf ngMock.$exceptionHandlerProvider\n   *\n   * @description\n   * Sets the logging mode.\n   *\n   * @param {string} mode Mode of operation, defaults to `rethrow`.\n   *\n   *   - `rethrow`: If any errors are are passed into the handler in tests, it typically\n   *                means that there is a bug in the application or test, so this mock will\n   *                make these tests fail.\n   *   - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores an\n   *            array of errors in `$exceptionHandler.errors`, to allow later assertion of them.\n   *            See {@link ngMock.$log#assertEmpty assertEmpty()} and\n   *             {@link ngMock.$log#reset reset()}\n   */\n  this.mode = function(mode) {\n    switch(mode) {\n      case 'rethrow':\n        handler = function(e) {\n          throw e;\n        };\n        break;\n      case 'log':\n        var errors = [];\n\n        handler = function(e) {\n          if (arguments.length == 1) {\n            errors.push(e);\n          } else {\n            errors.push([].slice.call(arguments, 0));\n          }\n        };\n\n        handler.errors = errors;\n        break;\n      default:\n        throw Error(\"Unknown mode '\" + mode + \"', only 'log'/'rethrow' modes are allowed!\");\n    }\n  };\n\n  this.$get = function() {\n    return handler;\n  };\n\n  this.mode('rethrow');\n};\n\n\n/**\n * @ngdoc service\n * @name ngMock.$log\n *\n * @description\n * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays\n * (one array per logging level). These arrays are exposed as `logs` property of each of the\n * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.\n *\n */\nangular.mock.$LogProvider = function() {\n\n  function concat(array1, array2, index) {\n    return array1.concat(Array.prototype.slice.call(array2, index));\n  }\n\n\n  this.$get = function () {\n    var $log = {\n      log: function() { $log.log.logs.push(concat([], arguments, 0)); },\n      warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },\n      info: function() { $log.info.logs.push(concat([], arguments, 0)); },\n      error: function() { $log.error.logs.push(concat([], arguments, 0)); }\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#reset\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Reset all of the logging arrays to empty.\n     */\n    $log.reset = function () {\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#log.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.log.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#warn.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.warn.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#info.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.info.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#error.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.error.logs = [];\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#assertEmpty\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.\n     */\n    $log.assertEmpty = function() {\n      var errors = [];\n      angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {\n        angular.forEach($log[logLevel].logs, function(log) {\n          angular.forEach(log, function (logItem) {\n            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\\n' + (logItem.stack || ''));\n          });\n        });\n      });\n      if (errors.length) {\n        errors.unshift(\"Expected $log to be empty! Either a message was logged unexpectedly, or an expected \" +\n          \"log message was not checked and removed:\");\n        errors.push('');\n        throw new Error(errors.join('\\n---------\\n'));\n      }\n    };\n\n    $log.reset();\n    return $log;\n  };\n};\n\n\n(function() {\n  var R_ISO8061_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?:\\:?(\\d\\d)(?:\\:?(\\d\\d)(?:\\.(\\d{3}))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d)))?$/;\n\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8061_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n  function int(str) {\n    return parseInt(str, 10);\n  }\n\n  function padNumber(num, digits, trim) {\n    var neg = '';\n    if (num < 0) {\n      neg =  '-';\n      num = -num;\n    }\n    num = '' + num;\n    while(num.length < digits) num = '0' + num;\n    if (trim)\n      num = num.substr(num.length - digits);\n    return neg + num;\n  }\n\n\n  /**\n   * @ngdoc object\n   * @name angular.mock.TzDate\n   * @description\n   *\n   * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.\n   *\n   * Mock of the Date type which has its timezone specified via constroctor arg.\n   *\n   * The main purpose is to create Date-like instances with timezone fixed to the specified timezone\n   * offset, so that we can test code that depends on local timezone settings without dependency on\n   * the time zone settings of the machine where the code is running.\n   *\n   * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)\n   * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*\n   *\n   * @example\n   * !!!! WARNING !!!!!\n   * This is not a complete Date object so only methods that were implemented can be called safely.\n   * To make matters worse, TzDate instances inherit stuff from Date via a prototype.\n   *\n   * We do our best to intercept calls to \"unimplemented\" methods, but since the list of methods is\n   * incomplete we might be missing some non-standard methods. This can result in errors like:\n   * \"Date.prototype.foo called on incompatible Object\".\n   *\n   * <pre>\n   * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');\n   * newYearInBratislava.getTimezoneOffset() => -60;\n   * newYearInBratislava.getFullYear() => 2010;\n   * newYearInBratislava.getMonth() => 0;\n   * newYearInBratislava.getDate() => 1;\n   * newYearInBratislava.getHours() => 0;\n   * newYearInBratislava.getMinutes() => 0;\n   * </pre>\n   *\n   */\n  angular.mock.TzDate = function (offset, timestamp) {\n    var self = new Date(0);\n    if (angular.isString(timestamp)) {\n      var tsStr = timestamp;\n\n      self.origDate = jsonStringToDate(timestamp);\n\n      timestamp = self.origDate.getTime();\n      if (isNaN(timestamp))\n        throw {\n          name: \"Illegal Argument\",\n          message: \"Arg '\" + tsStr + \"' passed into TzDate constructor is not a valid date string\"\n        };\n    } else {\n      self.origDate = new Date(timestamp);\n    }\n\n    var localOffset = new Date(timestamp).getTimezoneOffset();\n    self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;\n    self.date = new Date(timestamp + self.offsetDiff);\n\n    self.getTime = function() {\n      return self.date.getTime() - self.offsetDiff;\n    };\n\n    self.toLocaleDateString = function() {\n      return self.date.toLocaleDateString();\n    };\n\n    self.getFullYear = function() {\n      return self.date.getFullYear();\n    };\n\n    self.getMonth = function() {\n      return self.date.getMonth();\n    };\n\n    self.getDate = function() {\n      return self.date.getDate();\n    };\n\n    self.getHours = function() {\n      return self.date.getHours();\n    };\n\n    self.getMinutes = function() {\n      return self.date.getMinutes();\n    };\n\n    self.getSeconds = function() {\n      return self.date.getSeconds();\n    };\n\n    self.getTimezoneOffset = function() {\n      return offset * 60;\n    };\n\n    self.getUTCFullYear = function() {\n      return self.origDate.getUTCFullYear();\n    };\n\n    self.getUTCMonth = function() {\n      return self.origDate.getUTCMonth();\n    };\n\n    self.getUTCDate = function() {\n      return self.origDate.getUTCDate();\n    };\n\n    self.getUTCHours = function() {\n      return self.origDate.getUTCHours();\n    };\n\n    self.getUTCMinutes = function() {\n      return self.origDate.getUTCMinutes();\n    };\n\n    self.getUTCSeconds = function() {\n      return self.origDate.getUTCSeconds();\n    };\n\n    self.getUTCMilliseconds = function() {\n      return self.origDate.getUTCMilliseconds();\n    };\n\n    self.getDay = function() {\n      return self.date.getDay();\n    };\n\n    // provide this method only on browsers that already have it\n    if (self.toISOString) {\n      self.toISOString = function() {\n        return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +\n              padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +\n              padNumber(self.origDate.getUTCDate(), 2) + 'T' +\n              padNumber(self.origDate.getUTCHours(), 2) + ':' +\n              padNumber(self.origDate.getUTCMinutes(), 2) + ':' +\n              padNumber(self.origDate.getUTCSeconds(), 2) + '.' +\n              padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'\n      }\n    }\n\n    //hide all methods not implemented in this mock that the Date prototype exposes\n    var unimplementedMethods = ['getMilliseconds', 'getUTCDay',\n        'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',\n        'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',\n        'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',\n        'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',\n        'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];\n\n    angular.forEach(unimplementedMethods, function(methodName) {\n      self[methodName] = function() {\n        throw Error(\"Method '\" + methodName + \"' is not implemented in the TzDate mock\");\n      };\n    });\n\n    return self;\n  };\n\n  //make \"tzDateInstance instanceof Date\" return true\n  angular.mock.TzDate.prototype = Date.prototype;\n})();\n\n\n/**\n * @ngdoc function\n * @name angular.mock.dump\n * @description\n *\n * *NOTE*: this is not an injectable instance, just a globally available function.\n *\n * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.\n *\n * This method is also available on window, where it can be used to display objects on debug console.\n *\n * @param {*} object - any object to turn into string.\n * @return {string} a serialized string of the argument\n */\nangular.mock.dump = function(object) {\n  return serialize(object);\n\n  function serialize(object) {\n    var out;\n\n    if (angular.isElement(object)) {\n      object = angular.element(object);\n      out = angular.element('<div></div>');\n      angular.forEach(object, function(element) {\n        out.append(angular.element(element).clone());\n      });\n      out = out.html();\n    } else if (angular.isArray(object)) {\n      out = [];\n      angular.forEach(object, function(o) {\n        out.push(serialize(o));\n      });\n      out = '[ ' + out.join(', ') + ' ]';\n    } else if (angular.isObject(object)) {\n      if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {\n        out = serializeScope(object);\n      } else if (object instanceof Error) {\n        out = object.stack || ('' + object.name + ': ' + object.message);\n      } else {\n        out = angular.toJson(object, true);\n      }\n    } else {\n      out = String(object);\n    }\n\n    return out;\n  }\n\n  function serializeScope(scope, offset) {\n    offset = offset ||  '  ';\n    var log = [offset + 'Scope(' + scope.$id + '): {'];\n    for ( var key in scope ) {\n      if (scope.hasOwnProperty(key) && !key.match(/^(\\$|this)/)) {\n        log.push('  ' + key + ': ' + angular.toJson(scope[key]));\n      }\n    }\n    var child = scope.$$childHead;\n    while(child) {\n      log.push(serializeScope(child, offset + '  '));\n      child = child.$$nextSibling;\n    }\n    log.push('}');\n    return log.join('\\n' + offset);\n  }\n};\n\n/**\n * @ngdoc object\n * @name ngMock.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for unit testing application that use the\n * {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less\n * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.\n *\n * During unit testing, we want our unit tests to run quickly and have no external dependencies so\n * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or\n * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is\n * to verify whether a certain request has been sent or not, or alternatively just let the\n * application make requests, respond with pre-trained responses and assert that the end result is\n * what we expect it to be.\n *\n * This mock implementation can be used to respond with static or dynamic responses via the\n * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).\n *\n * When an Angular application needs some data from a server, it calls the $http service, which\n * sends the request to a real server using $httpBackend service. With dependency injection, it is\n * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify\n * the requests and respond with some testing data without sending a request to real server.\n *\n * There are two ways to specify what test data should be returned as http responses by the mock\n * backend when the code under test makes http requests:\n *\n * - `$httpBackend.expect` - specifies a request expectation\n * - `$httpBackend.when` - specifies a backend definition\n *\n *\n * # Request Expectations vs Backend Definitions\n *\n * Request expectations provide a way to make assertions about requests made by the application and\n * to define responses for those requests. The test will fail if the expected requests are not made\n * or they are made in the wrong order.\n *\n * Backend definitions allow you to define a fake backend for your application which doesn't assert\n * if a particular request was made or not, it just returns a trained response if a request is made.\n * The test will pass whether or not the request gets made during testing.\n *\n *\n * <table class=\"table\">\n *   <tr><th width=\"220px\"></th><th>Request expectations</th><th>Backend definitions</th></tr>\n *   <tr>\n *     <th>Syntax</th>\n *     <td>.expect(...).respond(...)</td>\n *     <td>.when(...).respond(...)</td>\n *   </tr>\n *   <tr>\n *     <th>Typical usage</th>\n *     <td>strict unit tests</td>\n *     <td>loose (black-box) unit testing</td>\n *   </tr>\n *   <tr>\n *     <th>Fulfills multiple requests</th>\n *     <td>NO</td>\n *     <td>YES</td>\n *   </tr>\n *   <tr>\n *     <th>Order of requests matters</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Request required</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Response required</th>\n *     <td>optional (see below)</td>\n *     <td>YES</td>\n *   </tr>\n * </table>\n *\n * In cases where both backend definitions and request expectations are specified during unit\n * testing, the request expectations are evaluated first.\n *\n * If a request expectation has no response specified, the algorithm will search your backend\n * definitions for an appropriate response.\n *\n * If a request didn't match any expectation or if the expectation doesn't have the response\n * defined, the backend definitions are evaluated in sequential order to see if any of them match\n * the request. The response from the first matched definition is returned.\n *\n *\n * # Flushing HTTP requests\n *\n * The $httpBackend used in production, always responds to requests with responses asynchronously.\n * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are\n * hard to write, follow and maintain. At the same time the testing mock, can't respond\n * synchronously because that would change the execution of the code under test. For this reason the\n * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending\n * requests and thus preserving the async api of the backend, while allowing the test to execute\n * synchronously.\n *\n *\n * # Unit testing with mock $httpBackend\n *\n * <pre>\n   // controller\n   function MyController($scope, $http) {\n     $http.get('/auth.py').success(function(data) {\n       $scope.user = data;\n     });\n\n     this.saveMessage = function(message) {\n       $scope.status = 'Saving...';\n       $http.post('/add-msg.py', message).success(function(response) {\n         $scope.status = '';\n       }).error(function() {\n         $scope.status = 'ERROR!';\n       });\n     };\n   }\n\n   // testing controller\n   var $httpBackend;\n\n   beforeEach(inject(function($injector) {\n     $httpBackend = $injector.get('$httpBackend');\n\n     // backend definition common for all tests\n     $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});\n   }));\n\n\n   afterEach(function() {\n     $httpBackend.verifyNoOutstandingExpectation();\n     $httpBackend.verifyNoOutstandingRequest();\n   });\n\n\n   it('should fetch authentication token', function() {\n     $httpBackend.expectGET('/auth.py');\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n   });\n\n\n   it('should send msg to server', function() {\n     // now you don’t care about the authentication, but\n     // the controller will still send the request and\n     // $httpBackend will respond without you having to\n     // specify the expectation and response for this request\n     $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');\n\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n     controller.saveMessage('message content');\n     expect(controller.status).toBe('Saving...');\n     $httpBackend.flush();\n     expect(controller.status).toBe('');\n   });\n\n\n   it('should send auth header', function() {\n     $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {\n       // check if the header was send, if it wasn't the expectation won't\n       // match the request and the test will fail\n       return headers['Authorization'] == 'xxx';\n     }).respond(201, '');\n\n     var controller = scope.$new(MyController);\n     controller.saveMessage('whatever');\n     $httpBackend.flush();\n   });\n   </pre>\n */\nangular.mock.$HttpBackendProvider = function() {\n  this.$get = [createHttpBackendMock];\n};\n\n/**\n * General factory function for $httpBackend mock.\n * Returns instance for unit testing (when no arguments specified):\n *   - passing through is disabled\n *   - auto flushing is disabled\n *\n * Returns instance for e2e testing (when `$delegate` and `$browser` specified):\n *   - passing through (delegating request to real backend) is enabled\n *   - auto flushing is enabled\n *\n * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)\n * @param {Object=} $browser Auto-flushing enabled if specified\n * @return {Object} Instance of $httpBackend mock\n */\nfunction createHttpBackendMock($delegate, $browser) {\n  var definitions = [],\n      expectations = [],\n      responses = [],\n      responsesPush = angular.bind(responses, responses.push);\n\n  function createResponse(status, data, headers) {\n    if (angular.isFunction(status)) return status;\n\n    return function() {\n      return angular.isNumber(status)\n          ? [status, data, headers]\n          : [200, status, data];\n    };\n  }\n\n  // TODO(vojta): change params to: method, url, data, headers, callback\n  function $httpBackend(method, url, data, callback, headers) {\n    var xhr = new MockXhr(),\n        expectation = expectations[0],\n        wasExpected = false;\n\n    function prettyPrint(data) {\n      return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)\n          ? data\n          : angular.toJson(data);\n    }\n\n    if (expectation && expectation.match(method, url)) {\n      if (!expectation.matchData(data))\n        throw Error('Expected ' + expectation + ' with different data\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.data) + '\\nGOT:      ' + data);\n\n      if (!expectation.matchHeaders(headers))\n        throw Error('Expected ' + expectation + ' with different headers\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.headers) + '\\nGOT:      ' +\n            prettyPrint(headers));\n\n      expectations.shift();\n\n      if (expectation.response) {\n        responses.push(function() {\n          var response = expectation.response(method, url, data, headers);\n          xhr.$$respHeaders = response[2];\n          callback(response[0], response[1], xhr.getAllResponseHeaders());\n        });\n        return;\n      }\n      wasExpected = true;\n    }\n\n    var i = -1, definition;\n    while ((definition = definitions[++i])) {\n      if (definition.match(method, url, data, headers || {})) {\n        if (definition.response) {\n          // if $browser specified, we do auto flush all requests\n          ($browser ? $browser.defer : responsesPush)(function() {\n            var response = definition.response(method, url, data, headers);\n            xhr.$$respHeaders = response[2];\n            callback(response[0], response[1], xhr.getAllResponseHeaders());\n          });\n        } else if (definition.passThrough) {\n          $delegate(method, url, data, callback, headers);\n        } else throw Error('No response defined !');\n        return;\n      }\n    }\n    throw wasExpected ?\n        Error('No response defined !') :\n        Error('Unexpected request: ' + method + ' ' + url + '\\n' +\n              (expectation ? 'Expected ' + expectation : 'No more request expected'));\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#when\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current definition.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.when = function(method, url, data, headers) {\n    var definition = new MockHttpExpectation(method, url, data, headers),\n        chain = {\n          respond: function(status, data, headers) {\n            definition.response = createResponse(status, data, headers);\n          }\n        };\n\n    if ($browser) {\n      chain.passThrough = function() {\n        definition.passThrough = true;\n      };\n    }\n\n    definitions.push(definition);\n    return chain;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for GET requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for HEAD requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for DELETE requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for POST requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for PUT requests.  For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for JSONP requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n  createShortMethods('when');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expect\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current expectation.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *  request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.expect = function(method, url, data, headers) {\n    var expectation = new MockHttpExpectation(method, url, data, headers);\n    expectations.push(expectation);\n    return {\n      respond: function(status, data, headers) {\n        expectation.response = createResponse(status, data, headers);\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for GET requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled. See #expect for more info.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for HEAD requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for DELETE requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for POST requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PUT requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPATCH\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PATCH requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for JSONP requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n  createShortMethods('expect');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#flush\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Flushes all pending requests using the trained responses.\n   *\n   * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,\n   *   all pending requests will be flushed. If there are no pending requests when the flush method\n   *   is called an exception is thrown (as this typically a sign of programming error).\n   */\n  $httpBackend.flush = function(count) {\n    if (!responses.length) throw Error('No pending request to flush !');\n\n    if (angular.isDefined(count)) {\n      while (count--) {\n        if (!responses.length) throw Error('No more pending request to flush !');\n        responses.shift()();\n      }\n    } else {\n      while (responses.length) {\n        responses.shift()();\n      }\n    }\n    $httpBackend.verifyNoOutstandingExpectation();\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingExpectation\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that all of the requests defined via the `expect` api were made. If any of the\n   * requests were not made, verifyNoOutstandingExpectation throws an exception.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyExpectations);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingExpectation = function() {\n    if (expectations.length) {\n      throw Error('Unsatisfied requests: ' + expectations.join(', '));\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingRequest\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that there are no outstanding requests that need to be flushed.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyNoOutstandingRequest);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingRequest = function() {\n    if (responses.length) {\n      throw Error('Unflushed requests: ' + responses.length);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#resetExpectations\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Resets all request expectations, but preserves all backend definitions. Typically, you would\n   * call resetExpectations during a multiple-phase test when you want to reuse the same instance of\n   * $httpBackend mock.\n   */\n  $httpBackend.resetExpectations = function() {\n    expectations.length = 0;\n    responses.length = 0;\n  };\n\n  return $httpBackend;\n\n\n  function createShortMethods(prefix) {\n    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {\n     $httpBackend[prefix + method] = function(url, headers) {\n       return $httpBackend[prefix](method, url, undefined, headers)\n     }\n    });\n\n    angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {\n      $httpBackend[prefix + method] = function(url, data, headers) {\n        return $httpBackend[prefix](method, url, data, headers)\n      }\n    });\n  }\n}\n\nfunction MockHttpExpectation(method, url, data, headers) {\n\n  this.data = data;\n  this.headers = headers;\n\n  this.match = function(m, u, d, h) {\n    if (method != m) return false;\n    if (!this.matchUrl(u)) return false;\n    if (angular.isDefined(d) && !this.matchData(d)) return false;\n    if (angular.isDefined(h) && !this.matchHeaders(h)) return false;\n    return true;\n  };\n\n  this.matchUrl = function(u) {\n    if (!url) return true;\n    if (angular.isFunction(url.test)) return url.test(u);\n    return url == u;\n  };\n\n  this.matchHeaders = function(h) {\n    if (angular.isUndefined(headers)) return true;\n    if (angular.isFunction(headers)) return headers(h);\n    return angular.equals(headers, h);\n  };\n\n  this.matchData = function(d) {\n    if (angular.isUndefined(data)) return true;\n    if (data && angular.isFunction(data.test)) return data.test(d);\n    if (data && !angular.isString(data)) return angular.toJson(data) == d;\n    return data == d;\n  };\n\n  this.toString = function() {\n    return method + ' ' + url;\n  };\n}\n\nfunction MockXhr() {\n\n  // hack for testing $http, $httpBackend\n  MockXhr.$$lastInstance = this;\n\n  this.open = function(method, url, async) {\n    this.$$method = method;\n    this.$$url = url;\n    this.$$async = async;\n    this.$$reqHeaders = {};\n    this.$$respHeaders = {};\n  };\n\n  this.send = function(data) {\n    this.$$data = data;\n  };\n\n  this.setRequestHeader = function(key, value) {\n    this.$$reqHeaders[key] = value;\n  };\n\n  this.getResponseHeader = function(name) {\n    // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last\n    var header = this.$$respHeaders[name];\n    if (header) return header;\n\n    name = angular.lowercase(name);\n    header = this.$$respHeaders[name];\n    if (header) return header;\n\n    header = undefined;\n    angular.forEach(this.$$respHeaders, function(headerVal, headerName) {\n      if (!header && angular.lowercase(headerName) == name) header = headerVal;\n    });\n    return header;\n  };\n\n  this.getAllResponseHeaders = function() {\n    var lines = [];\n\n    angular.forEach(this.$$respHeaders, function(value, key) {\n      lines.push(key + ': ' + value);\n    });\n    return lines.join('\\n');\n  };\n\n  this.abort = angular.noop;\n}\n\n\n/**\n * @ngdoc function\n * @name ngMock.$timeout\n * @description\n *\n * This service is just a simple decorator for {@link ng.$timeout $timeout} service\n * that adds a \"flush\" method.\n */\n\n/**\n * @ngdoc method\n * @name ngMock.$timeout#flush\n * @methodOf ngMock.$timeout\n * @description\n *\n * Flushes the queue of pending tasks.\n */\n\n/**\n *\n */\nangular.mock.$RootElementProvider = function() {\n  this.$get = function() {\n    return angular.element('<div ng-app></div>');\n  }\n};\n\n/**\n * @ngdoc overview\n * @name ngMock\n * @description\n *\n * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful\n * mocks to the {@link AUTO.$injector $injector}.\n */\nangular.module('ngMock', ['ng']).provider({\n  $browser: angular.mock.$BrowserProvider,\n  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,\n  $log: angular.mock.$LogProvider,\n  $httpBackend: angular.mock.$HttpBackendProvider,\n  $rootElement: angular.mock.$RootElementProvider\n}).config(function($provide) {\n  $provide.decorator('$timeout', function($delegate, $browser) {\n    $delegate.flush = function() {\n      $browser.defer.flush();\n    };\n    return $delegate;\n  });\n});\n\n\n/**\n * @ngdoc overview\n * @name ngMockE2E\n * @description\n *\n * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.\n * Currently there is only one mock present in this module -\n * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.\n */\nangular.module('ngMockE2E', ['ng']).config(function($provide) {\n  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);\n});\n\n/**\n * @ngdoc object\n * @name ngMockE2E.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of\n * applications that use the {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for unit testing please see\n * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.\n *\n * This implementation can be used to respond with static or dynamic responses via the `when` api\n * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the\n * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch\n * templates from a webserver).\n *\n * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application\n * is being developed with the real backend api replaced with a mock, it is often desirable for\n * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch\n * templates or static files from the webserver). To configure the backend with this behavior\n * use the `passThrough` request handler of `when` instead of `respond`.\n *\n * Additionally, we don't want to manually have to flush mocked out requests like we do during unit\n * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests\n * automatically, closely simulating the behavior of the XMLHttpRequest object.\n *\n * To setup the application to run with this http backend, you have to create a module that depends\n * on the `ngMockE2E` and your application modules and defines the fake backend:\n *\n * <pre>\n *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);\n *   myAppDev.run(function($httpBackend) {\n *     phones = [{name: 'phone1'}, {name: 'phone2'}];\n *\n *     // returns the current list of phones\n *     $httpBackend.whenGET('/phones').respond(phones);\n *\n *     // adds a new phone to the phones array\n *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {\n *       phones.push(angular.fromJSON(data));\n *     });\n *     $httpBackend.whenGET(/^\\/templates\\//).passThrough();\n *     //...\n *   });\n * </pre>\n *\n * Afterwards, bootstrap your app with this new module.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#when\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition.\n *\n * @param {string} method HTTP method.\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n *   object and returns true if the headers match the current definition.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n *\n *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n *    – The respond method takes a set of static data to be returned or a function that can return\n *    an array containing response status (number), response data (string) and response headers\n *    (Object).\n *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`\n *    handler, will be pass through to the real backend (an XHR request will be made to the\n *    server.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenGET\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for GET requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenHEAD\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for HEAD requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenDELETE\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for DELETE requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPOST\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for POST requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPUT\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PUT requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPATCH\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PATCH requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenJSONP\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for JSONP requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\nangular.mock.e2e = {};\nangular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];\n\n\nangular.mock.clearDataCache = function() {\n  var key,\n      cache = angular.element.cache;\n\n  for(key in cache) {\n    if (cache.hasOwnProperty(key)) {\n      var handle = cache[key].handle;\n\n      handle && angular.element(handle.elem).unbind();\n      delete cache[key];\n    }\n  }\n};\n\n\nwindow.jstestdriver && (function(window) {\n  /**\n   * Global method to output any number of objects into JSTD console. Useful for debugging.\n   */\n  window.dump = function() {\n    var args = [];\n    angular.forEach(arguments, function(arg) {\n      args.push(angular.mock.dump(arg));\n    });\n    jstestdriver.console.log.apply(jstestdriver.console, args);\n    if (window.console) {\n      window.console.log.apply(window.console, args);\n    }\n  };\n})(window);\n\n\nwindow.jasmine && (function(window) {\n\n  afterEach(function() {\n    var spec = getCurrentSpec();\n    var injector = spec.$injector;\n\n    spec.$injector = null;\n    spec.$modules = null;\n\n    if (injector) {\n      injector.get('$rootElement').unbind();\n      injector.get('$browser').pollFns.length = 0;\n    }\n\n    angular.mock.clearDataCache();\n\n    // clean up jquery's fragment cache\n    angular.forEach(angular.element.fragments, function(val, key) {\n      delete angular.element.fragments[key];\n    });\n\n    MockXhr.$$lastInstance = null;\n\n    angular.forEach(angular.callbacks, function(val, key) {\n      delete angular.callbacks[key];\n    });\n    angular.callbacks.counter = 0;\n  });\n\n  function getCurrentSpec() {\n    return jasmine.getEnv().currentSpec;\n  }\n\n  function isSpecRunning() {\n    var spec = getCurrentSpec();\n    return spec && spec.queue.running;\n  }\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.module\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * This function registers a module configuration code. It collects the configuration information\n   * which will be used when the injector is created by {@link angular.mock.inject inject}.\n   *\n   * See {@link angular.mock.inject inject} for usage example\n   *\n   * @param {...(string|Function)} fns any number of modules which are represented as string\n   *        aliases or as anonymous module initialization functions. The modules are used to\n   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.\n   */\n  window.module = angular.mock.module = function() {\n    var moduleFns = Array.prototype.slice.call(arguments, 0);\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      if (spec.$injector) {\n        throw Error('Injector already created, can not register a module!');\n      } else {\n        var modules = spec.$modules || (spec.$modules = []);\n        angular.forEach(moduleFns, function(module) {\n          modules.push(module);\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.inject\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * The inject function wraps a function into an injectable function. The inject() creates new\n   * instance of {@link AUTO.$injector $injector} per test, which is then used for\n   * resolving references.\n   *\n   * See also {@link angular.mock.module module}\n   *\n   * Example of what a typical jasmine tests looks like with the inject method.\n   * <pre>\n   *\n   *   angular.module('myApplicationModule', [])\n   *       .value('mode', 'app')\n   *       .value('version', 'v1.0.1');\n   *\n   *\n   *   describe('MyApp', function() {\n   *\n   *     // You need to load modules that you want to test,\n   *     // it loads only the \"ng\" module by default.\n   *     beforeEach(module('myApplicationModule'));\n   *\n   *\n   *     // inject() is used to inject arguments of all given functions\n   *     it('should provide a version', inject(function(mode, version) {\n   *       expect(version).toEqual('v1.0.1');\n   *       expect(mode).toEqual('app');\n   *     }));\n   *\n   *\n   *     // The inject and module method can also be used inside of the it or beforeEach\n   *     it('should override a version and test the new version is injected', function() {\n   *       // module() takes functions or strings (module aliases)\n   *       module(function($provide) {\n   *         $provide.value('version', 'overridden'); // override version here\n   *       });\n   *\n   *       inject(function(version) {\n   *         expect(version).toEqual('overridden');\n   *       });\n   *     ));\n   *   });\n   *\n   * </pre>\n   *\n   * @param {...Function} fns any number of functions which will be injected using the injector.\n   */\n  window.inject = angular.mock.inject = function() {\n    var blockFns = Array.prototype.slice.call(arguments, 0);\n    var errorForStack = new Error('Declaration Location');\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      var modules = spec.$modules || [];\n      modules.unshift('ngMock');\n      modules.unshift('ng');\n      var injector = spec.$injector;\n      if (!injector) {\n        injector = spec.$injector = angular.injector(modules);\n      }\n      for(var i = 0, ii = blockFns.length; i < ii; i++) {\n        try {\n          injector.invoke(blockFns[i] || angular.noop, this);\n        } catch (e) {\n          if(e.stack) e.stack +=  '\\n' + errorForStack.stack;\n          throw e;\n        } finally {\n          errorForStack = null;\n        }\n      }\n    }\n  };\n})(window);\n"
  },
  {
    "path": "chapter3/recipe8/test/lib/angular/angular-scenario.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Mar 21 12:46:34 2012 -0700\n */\n(function( window, undefined ) {\n'use strict';\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.7.2\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in array && array[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n\t\tvar exec,\n\t\t\tbulk = key == null,\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\n\t\t// Sets many values\n\t\tif ( key && typeof key === \"object\" ) {\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n\t\t\t}\n\t\t\tchainable = 1;\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = pass === undefined && jQuery.isFunction( value );\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations only iterate when executing function values\n\t\t\t\tif ( exec ) {\n\t\t\t\t\texec = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn exec.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\n\t\t\t\t// Otherwise they run against the entire set\n\t\t\t\t} else {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor (; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchainable = 1;\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfired = true;\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar length = list.length;\n\t\t\t\t\tadd( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory || memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tfragment,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tpixelMargin: true\n\t};\n\n\t// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead\n\tjQuery.boxModel = support.boxModel = (document.compatMode === \"CSS1Compat\");\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor ( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\tfragment.removeChild( div );\n\n\t// Null elements to avoid leaks in IE\n\tfragment = select = opt = div = input = null;\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tmarginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,\n\t\t\tpaddingMarginBorderVisibility, paddingMarginBorder,\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tconMarginTop = 1;\n\t\tpaddingMarginBorder = \"padding:0;margin:0;border:\";\n\t\tpositionTopLeftWidthHeight = \"position:absolute;top:0;left:0;width:1px;height:1px;\";\n\t\tpaddingMarginBorderVisibility = paddingMarginBorder + \"0;visibility:hidden;\";\n\t\tstyle = \"style='\" + positionTopLeftWidthHeight + paddingMarginBorder + \"5px solid #000;\";\n\t\thtml = \"<div \" + style + \"display:block;'><div style='\" + paddingMarginBorder + \"0;display:block;overflow:hidden;'></div></div>\" +\n\t\t\t\"<table \" + style + \"' cellpadding='0' cellspacing='0'>\" +\n\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = paddingMarginBorderVisibility + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td style='\" + paddingMarginBorder + \"0;display:none'></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName( \"td\" );\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t// gets computed margin-right based on width of container. For more\n\t\t// info see bug #3333\n\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tmarginDiv = document.createElement( \"div\" );\n\t\t\tmarginDiv.style.width = \"0\";\n\t\t\tmarginDiv.style.marginRight = \"0\";\n\t\t\tdiv.style.width = \"2px\";\n\t\t\tdiv.appendChild( marginDiv );\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\t// (IE < 8 does this)\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.width = div.style.padding = \"1px\";\n\t\t\tdiv.style.border = 0;\n\t\t\tdiv.style.overflow = \"hidden\";\n\t\t\tdiv.style.display = \"inline\";\n\t\t\tdiv.style.zoom = 1;\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.style.overflow = \"visible\";\n\t\t\tdiv.innerHTML = \"<div style='width:5px;'></div>\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\t\t}\n\n\t\tdiv.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;\n\t\tdiv.innerHTML = html;\n\n\t\touter = div.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.style.marginTop = \"1%\";\n\t\t\tsupport.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== \"1%\";\n\t\t}\n\n\t\tif ( typeof container.style.zoom !== \"undefined\" ) {\n\t\t\tcontainer.style.zoom = 1;\n\t\t}\n\n\t\tbody.removeChild( container );\n\t\tmarginDiv = div = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\treturn support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ internalKey ] : internalKey;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ internalKey ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( internalKey );\n\t\t\t} else {\n\t\t\t\telem[ internalKey ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, part, attr, name, l,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = elem.attributes;\n\t\t\t\t\tfor ( l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split( \".\", 2 );\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\t\tpart = parts[1] + \"!\";\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\tdata = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\tif ( data === undefined && elem ) {\n\t\t\t\t\tdata = jQuery.data( elem, key );\n\t\t\t\t\tdata = dataAttr( elem, key, data );\n\t\t\t\t}\n\n\t\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\t\tdata;\n\t\t\t}\n\n\t\t\tparts[1] = value;\n\t\t\tthis.each(function() {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.triggerHandler( \"setData\" + part, parts );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + part, parts );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, false );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\thooks = {};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( object );\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, l, isBool,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\t\t\tattrNames = value.toLowerCase().split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tisBool = rboolean.test( name );\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\t// Do not do this for boolean attributes (see #10870)\n\t\t\t\t\tif ( !isBool ) {\n\t\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\t}\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( isBool && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true,\n\t\tcoords: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = \"\" + value );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+)?\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\tvar attrs = elem.attributes || {};\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || (attrs.id || {}).value === m[2]) &&\n\t\t\t(!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tquick: selector && quickParse( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t ( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\told = null;\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\tspecial = jQuery.event.special[ event.type ] || {},\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n\t\t\t// Pregenerate a single jQuery object for reuse with .is()\n\t\t\tjqcur = jQuery(this);\n\t\t\tjqcur.context = this.ownerDocument || this;\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process events on disabled elements (#6911, #8165)\n\t\t\t\tif ( cur.disabled !== true ) {\n\t\t\t\t\tselMatch = {};\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tjqcur[0] = cur;\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\t\tselMatch[ sel ] = (\n\t\t\t\t\t\t\t\thandleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\tret;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\t\t\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\telem._change_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) { // && selector != null\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( var type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\n\t\t\tparts.push( m[1] );\n\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\t\t/* falls through */\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n// Expose origPOS\n// \"global\" as in regardless of relation to brackets/parens\nExpr.match.globalPOS = origPOS;\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry {\n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.globalPOS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\tPOS.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery.clean(arguments) );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tnull;\n\t\t\t}\n\n\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, function( i, elem ) {\n\t\t\t\t\tif ( elem.src ) {\n\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\turl: elem.src,\n\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\tdataType: \"script\"\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\n\t// IE blanks contents when cloning scripts\n\t} else if ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdest.text = src.text;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n\n\t// Clear flags for bubbling special change/submit events, they must\n\t// be reattached when the newly cloned events are first activated\n\tdest.removeAttribute( \"_submit_attached\" );\n\tdest.removeAttribute( \"_change_attached\" );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n\t// Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n\tvar div = document.createElement( \"div\" );\n\tsafeFragment.appendChild( div );\n\n\tdiv.innerHTML = elem.outerHTML;\n\treturn div.firstChild;\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t\tclone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ?\n\t\t\t\telem.cloneNode( true ) :\n\t\t\t\tshimCloneNode( elem );\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType, script, j,\n\t\t\t\tret = [];\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\"),\n\t\t\t\t\t\tsafeChildNodes = safeFragment.childNodes,\n\t\t\t\t\t\tremove;\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\n\t\t\t\t\t// Clear elements from DocumentFragment (safeFragment or otherwise)\n\t\t\t\t\t// to avoid hoarding elements. Fixes #11356\n\t\t\t\t\tif ( div ) {\n\t\t\t\t\t\tdiv.parentNode.removeChild( div );\n\n\t\t\t\t\t\t// Guard against -1 index exceptions in FF3.6\n\t\t\t\t\t\tif ( safeChildNodes.length > 0 ) {\n\t\t\t\t\t\t\tremove = safeChildNodes[ safeChildNodes.length - 1 ];\n\n\t\t\t\t\t\t\tif ( remove && remove.parentNode ) {\n\t\t\t\t\t\t\t\tremove.parentNode.removeChild( remove );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tscript = ret[i];\n\t\t\t\tif ( scripts && jQuery.nodeName( script, \"script\" ) && (!script.type || rscriptType.test( script.type )) ) {\n\t\t\t\t\tscripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( script.nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( script.getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( script );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnum = /^[\\-+]?(?:\\d*\\.)?\\d+$/i,\n\trnumnonpx = /^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\trmargin = /^margin/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\n\t// order is important!\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\treturn jQuery.access( this, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t}, name, value, arguments.length > 1 );\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {},\n\t\t\tret, name;\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// DEPRECATED in 1.3, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle, width,\n\t\t\tstyle = elem.style;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( (defaultView = elem.ownerDocument.defaultView) &&\n\t\t\t\t(computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// WebKit uses \"computed value (percentage if specified)\" instead of \"used value\" for margins\n\t\t// which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {\n\t\t\twidth = style.width;\n\t\t\tstyle.width = ret;\n\t\t\tret = computedStyle.width;\n\t\t\tstyle.width = width;\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( rnumnonpx.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\ti = name === \"width\" ? 1 : 0,\n\t\tlen = 4;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tfor ( ; i < len; i += 2 ) {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ];\n\t}\n\n\t// Computed unit is not pixels. Stop here and return.\n\tif ( rnumnonpx.test(val) ) {\n\t\treturn val;\n\t}\n\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tfor ( ; i < len; i += 2 ) {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val + \"px\";\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\treturn jQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\treturn rnum.test( value ) ?\n\t\t\t\tvalue + \"px\" :\n\t\t\t\tvalue;\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\treturn curCSS( elem, \"margin-right\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i,\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n\t\t\t\texpanded = {};\n\n\t\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n});\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = ( typeof s.data === \"string\" ) && /^application\\/x\\-www\\-form\\-urlencoded/.test( s.contentType );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t} catch( _ ) {\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( (display === \"\" && jQuery.css(elem, \"display\") === \"none\") ||\n\t\t\t\t\t\t!jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e, hooks, replace,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\t// first pass over propertys to expand / normalize\n\t\t\tfor ( p in prop ) {\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tif ( ( hooks = jQuery.cssHooks[ name ] ) && \"expand\" in hooks ) {\n\t\t\t\t\treplace = hooks.expand( prop[ name ] );\n\t\t\t\t\tdelete prop[ name ];\n\n\t\t\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t\t\t// also - reusing 'p' from above because we have the correct \"name\"\n\t\t\t\t\tfor ( p in replace ) {\n\t\t\t\t\t\tif ( ! ( p in prop ) ) {\n\t\t\t\t\t\t\tprop[ p ] = replace[ p ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( name in prop ) {\n\t\t\t\tval = prop[ name ];\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, index ) {\n\t\t\t\tvar hooks = data[ index ];\n\t\t\t\tjQuery.removeData( elem, index, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n\t\t\t\tstopQueue( this, data, index );\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ index ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ index ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p ) {\n\t\t\treturn p;\n\t\t},\n\t\tswing: function( p ) {\n\t\t\treturn ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tif ( self.options.hide ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t\t} else if ( self.options.show ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.end );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Ensure props that can't be negative don't go there on undershoot easing\njQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {\n\t// exclude marginTop, marginLeft, marginBottom and marginRight from this list\n\tif ( prop.indexOf( \"margin\" ) ) {\n\t\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( jQuery.support.boxModel ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar getOffset,\n\trtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tgetOffset = function( elem, doc, docElem, box ) {\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow( doc ),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tgetOffset = function( elem, doc, docElem ) {\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar elem = this[0],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn null;\n\t}\n\n\tif ( elem === doc.body ) {\n\t\treturn jQuery.offset.bodyOffset( elem );\n\t}\n\n\treturn getOffset( elem, doc, doc.documentElement );\n};\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t top ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tvar clientProp = \"client\" + name,\n\t\tscrollProp = \"scroll\" + name,\n\t\toffsetProp = \"offset\" + name;\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( value ) {\n\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\tvar doc, docElemProp, orig, ret;\n\n\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\t\tdoc = elem.document;\n\t\t\t\tdocElemProp = doc.documentElement[ clientProp ];\n\t\t\t\treturn jQuery.support.boxModel && docElemProp ||\n\t\t\t\t\tdoc.body && doc.body[ clientProp ] || docElemProp;\n\t\t\t}\n\n\t\t\t// Get document width or height\n\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t// when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]\n\t\t\t\t// so we can't use max, as it'll choose the incorrect offset[Width/Height]\n\t\t\t\t// instead we use the correct client[Width/Height]\n\t\t\t\t// support:IE6\n\t\t\t\tif ( doc[ clientProp ] >= doc[ scrollProp ] ) {\n\t\t\t\t\treturn doc[ clientProp ];\n\t\t\t\t}\n\n\t\t\t\treturn Math.max(\n\t\t\t\t\telem.body[ scrollProp ], doc[ scrollProp ],\n\t\t\t\t\telem.body[ offsetProp ], doc[ offsetProp ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get width or height on the element\n\t\t\tif ( value === undefined ) {\n\t\t\t\torig = jQuery.css( elem, type );\n\t\t\t\tret = parseFloat( orig );\n\t\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\t\t\t}\n\n\t\t\t// Set the width or height on the element\n\t\t\tjQuery( elem ).css( type, value );\n\t\t}, type, value, arguments.length, null );\n\t};\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );\n/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document){\n  var _jQuery = window.jQuery.noConflict(true);\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n\n/**\n * Setup file for the Scenario.\n * Must be first in the compilation/bootstrap list.\n */\n\n// Public namespace\nangular.scenario = angular.scenario || {};\n\n/**\n * Defines a new output format.\n *\n * @param {string} name the name of the new output format\n * @param {function()} fn function(context, runner) that generates the output\n */\nangular.scenario.output = angular.scenario.output || function(name, fn) {\n  angular.scenario.output[name] = fn;\n};\n\n/**\n * Defines a new DSL statement. If your factory function returns a Future\n * it's returned, otherwise the result is assumed to be a map of functions\n * for chaining. Chained functions are subject to the same rules.\n *\n * Note: All functions on the chain are bound to the chain scope so values\n *   set on \"this\" in your statement function are available in the chained\n *   functions.\n *\n * @param {string} name The name of the statement\n * @param {function()} fn Factory function(), return a function for\n *  the statement.\n */\nangular.scenario.dsl = angular.scenario.dsl || function(name, fn) {\n  angular.scenario.dsl[name] = function() {\n    function executeStatement(statement, args) {\n      var result = statement.apply(this, args);\n      if (angular.isFunction(result) || result instanceof angular.scenario.Future)\n        return result;\n      var self = this;\n      var chain = angular.extend({}, result);\n      angular.forEach(chain, function(value, name) {\n        if (angular.isFunction(value)) {\n          chain[name] = function() {\n            return executeStatement.call(self, value, arguments);\n          };\n        } else {\n          chain[name] = value;\n        }\n      });\n      return chain;\n    }\n    var statement = fn.apply(this, arguments);\n    return function() {\n      return executeStatement.call(this, statement, arguments);\n    };\n  };\n};\n\n/**\n * Defines a new matcher for use with the expects() statement. The value\n * this.actual (like in Jasmine) is available in your matcher to compare\n * against. Your function should return a boolean. The future is automatically\n * created for you.\n *\n * @param {string} name The name of the matcher\n * @param {function()} fn The matching function(expected).\n */\nangular.scenario.matcher = angular.scenario.matcher || function(name, fn) {\n  angular.scenario.matcher[name] = function(expected) {\n    var prefix = 'expect ' + this.future.name + ' ';\n    if (this.inverse) {\n      prefix += 'not ';\n    }\n    var self = this;\n    this.addFuture(prefix + name + ' ' + angular.toJson(expected),\n      function(done) {\n        var error;\n        self.actual = self.future.value;\n        if ((self.inverse && fn.call(self, expected)) ||\n            (!self.inverse && !fn.call(self, expected))) {\n          error = 'expected ' + angular.toJson(expected) +\n            ' but was ' + angular.toJson(self.actual);\n        }\n        done(error);\n    });\n  };\n};\n\n/**\n * Initialize the scenario runner and run !\n *\n * Access global window and document object\n * Access $runner through closure\n *\n * @param {Object=} config Config options\n */\nangular.scenario.setUpAndRun = function(config) {\n  var href = window.location.href;\n  var body = _jQuery(document.body);\n  var output = [];\n  var objModel = new angular.scenario.ObjectModel($runner);\n\n  if (config && config.scenario_output) {\n    output = config.scenario_output.split(',');\n  }\n\n  angular.forEach(angular.scenario.output, function(fn, name) {\n    if (!output.length || indexOf(output,name) != -1) {\n      var context = body.append('<div></div>').find('div:last');\n      context.attr('id', name);\n      fn.call({}, context, $runner, objModel);\n    }\n  });\n\n  if (!/^http/.test(href) && !/^https/.test(href)) {\n    body.append('<p id=\"system-error\"></p>');\n    body.find('#system-error').text(\n      'Scenario runner must be run using http or https. The protocol ' +\n      href.split(':')[0] + ':// is not supported.'\n    );\n    return;\n  }\n\n  var appFrame = body.append('<div id=\"application\"></div>').find('#application');\n  var application = new angular.scenario.Application(appFrame);\n\n  $runner.on('RunnerEnd', function() {\n    appFrame.css('display', 'none');\n    appFrame.find('iframe').attr('src', 'about:blank');\n  });\n\n  $runner.on('RunnerError', function(error) {\n    if (window.console) {\n      console.log(formatException(error));\n    } else {\n      // Do something for IE\n      alert(error);\n    }\n  });\n\n  $runner.run(application);\n};\n\n/**\n * Iterates through list with iterator function that must call the\n * continueFunction to continute iterating.\n *\n * @param {Array} list list to iterate over\n * @param {function()} iterator Callback function(value, continueFunction)\n * @param {function()} done Callback function(error, result) called when\n *   iteration finishes or an error occurs.\n */\nfunction asyncForEach(list, iterator, done) {\n  var i = 0;\n  function loop(error, index) {\n    if (index && index > i) {\n      i = index;\n    }\n    if (error || i >= list.length) {\n      done(error);\n    } else {\n      try {\n        iterator(list[i++], loop);\n      } catch (e) {\n        done(e);\n      }\n    }\n  }\n  loop();\n}\n\n/**\n * Formats an exception into a string with the stack trace, but limits\n * to a specific line length.\n *\n * @param {Object} error The exception to format, can be anything throwable\n * @param {Number=} [maxStackLines=5] max lines of the stack trace to include\n *  default is 5.\n */\nfunction formatException(error, maxStackLines) {\n  maxStackLines = maxStackLines || 5;\n  var message = error.toString();\n  if (error.stack) {\n    var stack = error.stack.split('\\n');\n    if (stack[0].indexOf(message) === -1) {\n      maxStackLines++;\n      stack.unshift(error.message);\n    }\n    message = stack.slice(0, maxStackLines).join('\\n');\n  }\n  return message;\n}\n\n/**\n * Returns a function that gets the file name and line number from a\n * location in the stack if available based on the call site.\n *\n * Note: this returns another function because accessing .stack is very\n * expensive in Chrome.\n *\n * @param {Number} offset Number of stack lines to skip\n */\nfunction callerFile(offset) {\n  var error = new Error();\n\n  return function() {\n    var line = (error.stack || '').split('\\n')[offset];\n\n    // Clean up the stack trace line\n    if (line) {\n      if (line.indexOf('@') !== -1) {\n        // Firefox\n        line = line.substring(line.indexOf('@')+1);\n      } else {\n        // Chrome\n        line = line.substring(line.indexOf('(')+1).replace(')', '');\n      }\n    }\n\n    return line || '';\n  };\n}\n\n/**\n * Triggers a browser event. Attempts to choose the right event if one is\n * not specified.\n *\n * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement\n * @param {string} type Optional event type.\n * @param {Array.<string>=} keys Optional list of pressed keys\n *        (valid values: 'alt', 'meta', 'shift', 'ctrl')\n */\nfunction browserTrigger(element, type, keys) {\n  if (element && !element.nodeName) element = element[0];\n  if (!element) return;\n  if (!type) {\n    type = {\n        'text':            'change',\n        'textarea':        'change',\n        'hidden':          'change',\n        'password':        'change',\n        'button':          'click',\n        'submit':          'click',\n        'reset':           'click',\n        'image':           'click',\n        'checkbox':        'click',\n        'radio':           'click',\n        'select-one':      'change',\n        'select-multiple': 'change'\n    }[lowercase(element.type)] || 'click';\n  }\n  if (lowercase(nodeName_(element)) == 'option') {\n    element.parentNode.value = element.value;\n    element = element.parentNode;\n    type = 'change';\n  }\n\n  keys = keys || [];\n  function pressed(key) {\n    return indexOf(keys, key) !== -1;\n  }\n\n  if (msie < 9) {\n    switch(element.type) {\n      case 'radio':\n      case 'checkbox':\n        element.checked = !element.checked;\n        break;\n    }\n    // WTF!!! Error: Unspecified error.\n    // Don't know why, but some elements when detached seem to be in inconsistent state and\n    // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)\n    // forcing the browser to compute the element position (by reading its CSS)\n    // puts the element in consistent state.\n    element.style.posLeft;\n\n    // TODO(vojta): create event objects with pressed keys to get it working on IE<9\n    var ret = element.fireEvent('on' + type);\n    if (lowercase(element.type) == 'submit') {\n      while(element) {\n        if (lowercase(element.nodeName) == 'form') {\n          element.fireEvent('onsubmit');\n          break;\n        }\n        element = element.parentNode;\n      }\n    }\n    return ret;\n  } else {\n    var evnt = document.createEvent('MouseEvents'),\n        originalPreventDefault = evnt.preventDefault,\n        iframe = _jQuery('#application iframe')[0],\n        appWindow = iframe ? iframe.contentWindow : window,\n        fakeProcessDefault = true,\n        finalProcessDefault,\n        angular = appWindow.angular || {};\n\n    // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208\n    angular['ff-684208-preventDefault'] = false;\n    evnt.preventDefault = function() {\n      fakeProcessDefault = false;\n      return originalPreventDefault.apply(evnt, arguments);\n    };\n\n    evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, pressed('ctrl'), pressed('alt'),\n                        pressed('shift'), pressed('meta'), 0, element);\n\n    element.dispatchEvent(evnt);\n    finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);\n\n    delete angular['ff-684208-preventDefault'];\n\n    return finalProcessDefault;\n  }\n}\n\n/**\n * Don't use the jQuery trigger method since it works incorrectly.\n *\n * jQuery notifies listeners and then changes the state of a checkbox and\n * does not create a real browser event. A real click changes the state of\n * the checkbox and then notifies listeners.\n *\n * To work around this we instead use our own handler that fires a real event.\n */\n(function(fn){\n  var parentTrigger = fn.trigger;\n  fn.trigger = function(type) {\n    if (/(click|change|keydown|blur|input)/.test(type)) {\n      var processDefaults = [];\n      this.each(function(index, node) {\n        processDefaults.push(browserTrigger(node, type));\n      });\n\n      // this is not compatible with jQuery - we return an array of returned values,\n      // so that scenario runner know whether JS code has preventDefault() of the event or not...\n      return processDefaults;\n    }\n    return parentTrigger.apply(this, arguments);\n  };\n})(_jQuery.fn);\n\n/**\n * Finds all bindings with the substring match of name and returns an\n * array of their values.\n *\n * @param {string} bindExp The name to match\n * @return {Array.<string>} String of binding values\n */\n_jQuery.fn.bindings = function(windowJquery, bindExp) {\n  var result = [], match,\n      bindSelector = '.ng-binding:visible';\n  if (angular.isString(bindExp)) {\n    bindExp = bindExp.replace(/\\s/g, '');\n    match = function (actualExp) {\n      if (actualExp) {\n        actualExp = actualExp.replace(/\\s/g, '');\n        if (actualExp == bindExp) return true;\n        if (actualExp.indexOf(bindExp) == 0) {\n          return actualExp.charAt(bindExp.length) == '|';\n        }\n      }\n    }\n  } else if (bindExp) {\n    match = function(actualExp) {\n      return actualExp && bindExp.exec(actualExp);\n    }\n  } else {\n    match = function(actualExp) {\n      return !!actualExp;\n    };\n  }\n  var selection = this.find(bindSelector);\n  if (this.is(bindSelector)) {\n    selection = selection.add(this);\n  }\n\n  function push(value) {\n    if (value == undefined) {\n      value = '';\n    } else if (typeof value != 'string') {\n      value = angular.toJson(value);\n    }\n    result.push('' + value);\n  }\n\n  selection.each(function() {\n    var element = windowJquery(this),\n        binding;\n    if (binding = element.data('$binding')) {\n      if (typeof binding == 'string') {\n        if (match(binding)) {\n          push(element.scope().$eval(binding));\n        }\n      } else {\n        if (!angular.isArray(binding)) {\n          binding = [binding];\n        }\n        for(var fns, j=0, jj=binding.length;  j<jj; j++) {\n          fns = binding[j];\n          if (fns.parts) {\n            fns = fns.parts;\n          } else {\n            fns = [fns];\n          }\n          for (var scope, fn, i = 0, ii = fns.length; i < ii; i++) {\n            if(match((fn = fns[i]).exp)) {\n              push(fn(scope = scope || element.scope()));\n            }\n          }\n        }\n      }\n    }\n  });\n  return result;\n};\n\n/**\n * Represents the application currently being tested and abstracts usage\n * of iframes or separate windows.\n *\n * @param {Object} context jQuery wrapper around HTML context.\n */\nangular.scenario.Application = function(context) {\n  this.context = context;\n  context.append(\n    '<h2>Current URL: <a href=\"about:blank\">None</a></h2>' +\n    '<div id=\"test-frames\"></div>'\n  );\n};\n\n/**\n * Gets the jQuery collection of frames. Don't use this directly because\n * frames may go stale.\n *\n * @private\n * @return {Object} jQuery collection\n */\nangular.scenario.Application.prototype.getFrame_ = function() {\n  return this.context.find('#test-frames iframe:last');\n};\n\n/**\n * Gets the window of the test runner frame. Always favor executeAction()\n * instead of this method since it prevents you from getting a stale window.\n *\n * @private\n * @return {Object} the window of the frame\n */\nangular.scenario.Application.prototype.getWindow_ = function() {\n  var contentWindow = this.getFrame_().prop('contentWindow');\n  if (!contentWindow)\n    throw 'Frame window is not accessible.';\n  return contentWindow;\n};\n\n/**\n * Changes the location of the frame.\n *\n * @param {string} url The URL. If it begins with a # then only the\n *   hash of the page is changed.\n * @param {function()} loadFn function($window, $document) Called when frame loads.\n * @param {function()} errorFn function(error) Called if any error when loading.\n */\nangular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorFn) {\n  var self = this;\n  var frame = this.getFrame_();\n  //TODO(esprehn): Refactor to use rethrow()\n  errorFn = errorFn || function(e) { throw e; };\n  if (url === 'about:blank') {\n    errorFn('Sandbox Error: Navigating to about:blank is not allowed.');\n  } else if (url.charAt(0) === '#') {\n    url = frame.attr('src').split('#')[0] + url;\n    frame.attr('src', url);\n    this.executeAction(loadFn);\n  } else {\n    frame.remove();\n    this.context.find('#test-frames').append('<iframe>');\n    frame = this.getFrame_();\n    frame.load(function() {\n      frame.unbind();\n      try {\n        self.executeAction(loadFn);\n      } catch (e) {\n        errorFn(e);\n      }\n    }).attr('src', url);\n  }\n  this.context.find('> h2 a').attr('href', url).text(url);\n};\n\n/**\n * Executes a function in the context of the tested application. Will wait\n * for all pending angular xhr requests before executing.\n *\n * @param {function()} action The callback to execute. function($window, $document)\n *  $document is a jQuery wrapped document.\n */\nangular.scenario.Application.prototype.executeAction = function(action) {\n  var self = this;\n  var $window = this.getWindow_();\n  if (!$window.document) {\n    throw 'Sandbox Error: Application document not accessible.';\n  }\n  if (!$window.angular) {\n    return action.call(this, $window, _jQuery($window.document));\n  }\n  angularInit($window.document, function(element) {\n    var $injector = $window.angular.element(element).injector();\n    var $element = _jQuery(element);\n\n    $element.injector = function() {\n      return $injector;\n    };\n\n    $injector.invoke(function($browser){\n      $browser.notifyWhenNoOutstandingRequests(function() {\n        action.call(self, $window, $element);\n      });\n    });\n  });\n};\n\n/**\n * The representation of define blocks. Don't used directly, instead use\n * define() in your tests.\n *\n * @param {string} descName Name of the block\n * @param {Object} parent describe or undefined if the root.\n */\nangular.scenario.Describe = function(descName, parent) {\n  this.only = parent && parent.only;\n  this.beforeEachFns = [];\n  this.afterEachFns = [];\n  this.its = [];\n  this.children = [];\n  this.name = descName;\n  this.parent = parent;\n  this.id = angular.scenario.Describe.id++;\n\n  /**\n   * Calls all before functions.\n   */\n  var beforeEachFns = this.beforeEachFns;\n  this.setupBefore = function() {\n    if (parent) parent.setupBefore.call(this);\n    angular.forEach(beforeEachFns, function(fn) { fn.call(this); }, this);\n  };\n\n  /**\n   * Calls all after functions.\n   */\n  var afterEachFns = this.afterEachFns;\n  this.setupAfter  = function() {\n    angular.forEach(afterEachFns, function(fn) { fn.call(this); }, this);\n    if (parent) parent.setupAfter.call(this);\n  };\n};\n\n// Shared Unique ID generator for every describe block\nangular.scenario.Describe.id = 0;\n\n// Shared Unique ID generator for every it (spec)\nangular.scenario.Describe.specId = 0;\n\n/**\n * Defines a block to execute before each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.beforeEach = function(body) {\n  this.beforeEachFns.push(body);\n};\n\n/**\n * Defines a block to execute after each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.afterEach = function(body) {\n  this.afterEachFns.push(body);\n};\n\n/**\n * Creates a new describe block that's a child of this one.\n *\n * @param {string} name Name of the block. Appended to the parent block's name.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.describe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Same as describe() but makes ddescribe blocks the only to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.ddescribe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  child.only = true;\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Use to disable a describe block.\n */\nangular.scenario.Describe.prototype.xdescribe = angular.noop;\n\n/**\n * Defines a test.\n *\n * @param {string} name Name of the test.\n * @param {function()} vody Body of the block.\n */\nangular.scenario.Describe.prototype.it = function(name, body) {\n  this.its.push({\n    id: angular.scenario.Describe.specId++,\n    definition: this,\n    only: this.only,\n    name: name,\n    before: this.setupBefore,\n    body: body,\n    after: this.setupAfter\n  });\n};\n\n/**\n * Same as it() but makes iit tests the only test to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.iit = function(name, body) {\n  this.it.apply(this, arguments);\n  this.its[this.its.length-1].only = true;\n};\n\n/**\n * Use to disable a test block.\n */\nangular.scenario.Describe.prototype.xit = angular.noop;\n\n/**\n * Gets an array of functions representing all the tests (recursively).\n * that can be executed with SpecRunner's.\n *\n * @return {Array<Object>} Array of it blocks {\n *   definition : Object // parent Describe\n *   only: boolean\n *   name: string\n *   before: Function\n *   body: Function\n *   after: Function\n *  }\n */\nangular.scenario.Describe.prototype.getSpecs = function() {\n  var specs = arguments[0] || [];\n  angular.forEach(this.children, function(child) {\n    child.getSpecs(specs);\n  });\n  angular.forEach(this.its, function(it) {\n    specs.push(it);\n  });\n  var only = [];\n  angular.forEach(specs, function(it) {\n    if (it.only) {\n      only.push(it);\n    }\n  });\n  return (only.length && only) || specs;\n};\n\n/**\n * A future action in a spec.\n *\n * @param {string} name of the future action\n * @param {function()} future callback(error, result)\n * @param {function()} Optional. function that returns the file/line number.\n */\nangular.scenario.Future = function(name, behavior, line) {\n  this.name = name;\n  this.behavior = behavior;\n  this.fulfilled = false;\n  this.value = undefined;\n  this.parser = angular.identity;\n  this.line = line || function() { return ''; };\n};\n\n/**\n * Executes the behavior of the closure.\n *\n * @param {function()} doneFn Callback function(error, result)\n */\nangular.scenario.Future.prototype.execute = function(doneFn) {\n  var self = this;\n  this.behavior(function(error, result) {\n    self.fulfilled = true;\n    if (result) {\n      try {\n        result = self.parser(result);\n      } catch(e) {\n        error = e;\n      }\n    }\n    self.value = error || result;\n    doneFn(error, result);\n  });\n};\n\n/**\n * Configures the future to convert it's final with a function fn(value)\n *\n * @param {function()} fn function(value) that returns the parsed value\n */\nangular.scenario.Future.prototype.parsedWith = function(fn) {\n  this.parser = fn;\n  return this;\n};\n\n/**\n * Configures the future to parse it's final value from JSON\n * into objects.\n */\nangular.scenario.Future.prototype.fromJson = function() {\n  return this.parsedWith(angular.fromJson);\n};\n\n/**\n * Configures the future to convert it's final value from objects\n * into JSON.\n */\nangular.scenario.Future.prototype.toJson = function() {\n  return this.parsedWith(angular.toJson);\n};\n\n/**\n * Maintains an object tree from the runner events.\n *\n * @param {Object} runner The scenario Runner instance to connect to.\n *\n * TODO(esprehn): Every output type creates one of these, but we probably\n *  want one global shared instance. Need to handle events better too\n *  so the HTML output doesn't need to do spec model.getSpec(spec.id)\n *  silliness.\n *\n * TODO(vojta) refactor on, emit methods (from all objects) - use inheritance\n */\nangular.scenario.ObjectModel = function(runner) {\n  var self = this;\n\n  this.specMap = {};\n  this.listeners = [];\n  this.value = {\n    name: '',\n    children: {}\n  };\n\n  runner.on('SpecBegin', function(spec) {\n    var block = self.value,\n        definitions = [];\n\n    angular.forEach(self.getDefinitionPath(spec), function(def) {\n      if (!block.children[def.name]) {\n        block.children[def.name] = {\n          id: def.id,\n          name: def.name,\n          children: {},\n          specs: {}\n        };\n      }\n      block = block.children[def.name];\n      definitions.push(def.name);\n    });\n\n    var it = self.specMap[spec.id] =\n             block.specs[spec.name] =\n             new angular.scenario.ObjectModel.Spec(spec.id, spec.name, definitions);\n\n    // forward the event\n    self.emit('SpecBegin', it);\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var it = self.getSpec(spec.id);\n    it.status = 'error';\n    it.error = error;\n\n    // forward the event\n    self.emit('SpecError', it, error);\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    complete(it);\n\n    // forward the event\n    self.emit('SpecEnd', it);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var it = self.getSpec(spec.id);\n    var step = new angular.scenario.ObjectModel.Step(step.name);\n    it.steps.push(step);\n\n    // forward the event\n    self.emit('StepBegin', it, step);\n  });\n\n  runner.on('StepEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    var step = it.getLastStep();\n    if (step.name !== step.name)\n      throw 'Events fired in the wrong order. Step names don\\'t match.';\n    complete(step);\n\n    // forward the event\n    self.emit('StepEnd', it, step);\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('failure', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepFailure', it, modelStep, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('error', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepError', it, modelStep, error);\n  });\n\n  runner.on('RunnerBegin', function() {\n    self.emit('RunnerBegin');\n  });\n  runner.on('RunnerEnd', function() {\n    self.emit('RunnerEnd');\n  });\n\n  function complete(item) {\n    item.endTime = new Date().getTime();\n    item.duration = item.endTime - item.startTime;\n    item.status = item.status || 'success';\n  }\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName Name of the event to add a handler for\n * @param {function()} listener Function that will be called when event is fired\n */\nangular.scenario.ObjectModel.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.ObjectModel.prototype.emit = function(eventName) {\n  var self = this,\n      args = Array.prototype.slice.call(arguments, 1),\n      eventName = eventName.toLowerCase();\n\n  if (this.listeners[eventName]) {\n    angular.forEach(this.listeners[eventName], function(listener) {\n      listener.apply(self, args);\n    });\n  }\n};\n\n/**\n * Computes the path of definition describe blocks that wrap around\n * this spec.\n *\n * @param spec Spec to compute the path for.\n * @return {Array<Describe>} The describe block path\n */\nangular.scenario.ObjectModel.prototype.getDefinitionPath = function(spec) {\n  var path = [];\n  var currentDefinition = spec.definition;\n  while (currentDefinition && currentDefinition.name) {\n    path.unshift(currentDefinition);\n    currentDefinition = currentDefinition.parent;\n  }\n  return path;\n};\n\n/**\n * Gets a spec by id.\n *\n * @param {string} The id of the spec to get the object for.\n * @return {Object} the Spec instance\n */\nangular.scenario.ObjectModel.prototype.getSpec = function(id) {\n  return this.specMap[id];\n};\n\n/**\n * A single it block.\n *\n * @param {string} id Id of the spec\n * @param {string} name Name of the spec\n * @param {Array<string>=} definitionNames List of all describe block names that wrap this spec\n */\nangular.scenario.ObjectModel.Spec = function(id, name, definitionNames) {\n  this.id = id;\n  this.name = name;\n  this.startTime = new Date().getTime();\n  this.steps = [];\n  this.fullDefinitionName = (definitionNames || []).join(' ');\n};\n\n/**\n * Adds a new step to the Spec.\n *\n * @param {string} step Name of the step (really name of the future)\n * @return {Object} the added step\n */\nangular.scenario.ObjectModel.Spec.prototype.addStep = function(name) {\n  var step = new angular.scenario.ObjectModel.Step(name);\n  this.steps.push(step);\n  return step;\n};\n\n/**\n * Gets the most recent step.\n *\n * @return {Object} the step\n */\nangular.scenario.ObjectModel.Spec.prototype.getLastStep = function() {\n  return this.steps[this.steps.length-1];\n};\n\n/**\n * Set status of the Spec from given Step\n *\n * @param {angular.scenario.ObjectModel.Step} step\n */\nangular.scenario.ObjectModel.Spec.prototype.setStatusFromStep = function(step) {\n  if (!this.status || step.status == 'error') {\n    this.status = step.status;\n    this.error = step.error;\n    this.line = step.line;\n  }\n};\n\n/**\n * A single step inside a Spec.\n *\n * @param {string} step Name of the step\n */\nangular.scenario.ObjectModel.Step = function(name) {\n  this.name = name;\n  this.startTime = new Date().getTime();\n};\n\n/**\n * Helper method for setting all error status related properties\n *\n * @param {string} status\n * @param {string} error\n * @param {string} line\n */\nangular.scenario.ObjectModel.Step.prototype.setErrorStatus = function(status, error, line) {\n  this.status = status;\n  this.error = error;\n  this.line = line;\n};\n\n/**\n * Runner for scenarios\n *\n * Has to be initialized before any test is loaded,\n * because it publishes the API into window (global space).\n */\nangular.scenario.Runner = function($window) {\n  this.listeners = [];\n  this.$window = $window;\n  this.rootDescribe = new angular.scenario.Describe();\n  this.currentDescribe = this.rootDescribe;\n  this.api = {\n    it: this.it,\n    iit: this.iit,\n    xit: angular.noop,\n    describe: this.describe,\n    ddescribe: this.ddescribe,\n    xdescribe: angular.noop,\n    beforeEach: this.beforeEach,\n    afterEach: this.afterEach\n  };\n  angular.forEach(this.api, angular.bind(this, function(fn, key) {\n    this.$window[key] = angular.bind(this, fn);\n  }));\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.Runner.prototype.emit = function(eventName) {\n  var self = this;\n  var args = Array.prototype.slice.call(arguments, 1);\n  eventName = eventName.toLowerCase();\n  if (!this.listeners[eventName])\n    return;\n  angular.forEach(this.listeners[eventName], function(listener) {\n    listener.apply(self, args);\n  });\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName The name of the event to add a handler for\n * @param {string} listener The fn(...) that takes the extra arguments from emit()\n */\nangular.scenario.Runner.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Defines a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.describe = function(name, body) {\n  var self = this;\n  this.currentDescribe.describe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Same as describe, but makes ddescribe the only blocks to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.ddescribe = function(name, body) {\n  var self = this;\n  this.currentDescribe.ddescribe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Defines a test in a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.it = function(name, body) {\n  this.currentDescribe.it(name, body);\n};\n\n/**\n * Same as it, but makes iit tests the only tests to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.iit = function(name, body) {\n  this.currentDescribe.iit(name, body);\n};\n\n/**\n * Defines a function to be called before each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.beforeEach = function(body) {\n  this.currentDescribe.beforeEach(body);\n};\n\n/**\n * Defines a function to be called after each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.afterEach = function(body) {\n  this.currentDescribe.afterEach(body);\n};\n\n/**\n * Creates a new spec runner.\n *\n * @private\n * @param {Object} scope parent scope\n */\nangular.scenario.Runner.prototype.createSpecRunner_ = function(scope) {\n  var child = scope.$new();\n  var Cls = angular.scenario.SpecRunner;\n\n  // Export all the methods to child scope manually as now we don't mess controllers with scopes\n  // TODO(vojta): refactor scenario runner so that these objects are not tightly coupled as current\n  for (var name in Cls.prototype)\n    child[name] = angular.bind(child, Cls.prototype[name]);\n\n  Cls.call(child);\n  return child;\n};\n\n/**\n * Runs all the loaded tests with the specified runner class on the\n * provided application.\n *\n * @param {angular.scenario.Application} application App to remote control.\n */\nangular.scenario.Runner.prototype.run = function(application) {\n  var self = this;\n  var $root = angular.injector(['ng']).get('$rootScope');\n  angular.extend($root, this);\n  angular.forEach(angular.scenario.Runner.prototype, function(fn, name) {\n    $root[name] = angular.bind(self, fn);\n  });\n  $root.application = application;\n  $root.emit('RunnerBegin');\n  asyncForEach(this.rootDescribe.getSpecs(), function(spec, specDone) {\n    var dslCache = {};\n    var runner = self.createSpecRunner_($root);\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      dslCache[key] = fn.call($root);\n    });\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      self.$window[key] = function() {\n        var line = callerFile(3);\n        var scope = runner.$new();\n\n        // Make the dsl accessible on the current chain\n        scope.dsl = {};\n        angular.forEach(dslCache, function(fn, key) {\n          scope.dsl[key] = function() {\n            return dslCache[key].apply(scope, arguments);\n          };\n        });\n\n        // Make these methods work on the current chain\n        scope.addFuture = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFuture.apply(scope, arguments);\n        };\n        scope.addFutureAction = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFutureAction.apply(scope, arguments);\n        };\n\n        return scope.dsl[key].apply(scope, arguments);\n      };\n    });\n    runner.run(spec, function() {\n      runner.$destroy();\n      specDone.apply(this, arguments);\n    });\n  },\n  function(error) {\n    if (error) {\n      self.emit('RunnerError', error);\n    }\n    self.emit('RunnerEnd');\n  });\n};\n\n/**\n * This class is the \"this\" of the it/beforeEach/afterEach method.\n * Responsibilities:\n *   - \"this\" for it/beforeEach/afterEach\n *   - keep state for single it/beforeEach/afterEach execution\n *   - keep track of all of the futures to execute\n *   - run single spec (execute each future)\n */\nangular.scenario.SpecRunner = function() {\n  this.futures = [];\n  this.afterIndex = 0;\n};\n\n/**\n * Executes a spec which is an it block with associated before/after functions\n * based on the describe nesting.\n *\n * @param {Object} spec A spec object\n * @param {function()} specDone function that is called when the spec finshes. Function(error, index)\n */\nangular.scenario.SpecRunner.prototype.run = function(spec, specDone) {\n  var self = this;\n  this.spec = spec;\n\n  this.emit('SpecBegin', spec);\n\n  try {\n    spec.before.call(this);\n    spec.body.call(this);\n    this.afterIndex = this.futures.length;\n    spec.after.call(this);\n  } catch (e) {\n    this.emit('SpecError', spec, e);\n    this.emit('SpecEnd', spec);\n    specDone();\n    return;\n  }\n\n  var handleError = function(error, done) {\n    if (self.error) {\n      return done();\n    }\n    self.error = true;\n    done(null, self.afterIndex);\n  };\n\n  asyncForEach(\n    this.futures,\n    function(future, futureDone) {\n      self.step = future;\n      self.emit('StepBegin', spec, future);\n      try {\n        future.execute(function(error) {\n          if (error) {\n            self.emit('StepFailure', spec, future, error);\n            self.emit('StepEnd', spec, future);\n            return handleError(error, futureDone);\n          }\n          self.emit('StepEnd', spec, future);\n          self.$window.setTimeout(function() { futureDone(); }, 0);\n        });\n      } catch (e) {\n        self.emit('StepError', spec, future, e);\n        self.emit('StepEnd', spec, future);\n        handleError(e, futureDone);\n      }\n    },\n    function(e) {\n      if (e) {\n        self.emit('SpecError', spec, e);\n      }\n      self.emit('SpecEnd', spec);\n      // Call done in a timeout so exceptions don't recursively\n      // call this function\n      self.$window.setTimeout(function() { specDone(); }, 0);\n    }\n  );\n};\n\n/**\n * Adds a new future action.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFuture = function(name, behavior, line) {\n  var future = new angular.scenario.Future(name, angular.bind(this, behavior), line);\n  this.futures.push(future);\n  return future;\n};\n\n/**\n * Adds a new future action to be executed on the application window.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior, line) {\n  var self = this;\n  var NG = /\\[ng\\\\\\:/;\n  return this.addFuture(name, function(done) {\n    this.application.executeAction(function($window, $document) {\n\n      //TODO(esprehn): Refactor this so it doesn't need to be in here.\n      $document.elements = function(selector) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        selector = (self.selector || '') + ' ' + (selector || '');\n        selector = _jQuery.trim(selector) || '*';\n        angular.forEach(args, function(value, index) {\n          selector = selector.replace('$' + (index + 1), value);\n        });\n        var result = $document.find(selector);\n        if (selector.match(NG)) {\n          angular.forEach(['[ng-','[data-ng-','[x-ng-'], function(value, index){\n            result = result.add(selector.replace(NG, value), $document);\n          });\n        }\n        if (!result.length) {\n          throw {\n            type: 'selector',\n            message: 'Selector ' + selector + ' did not match any elements.'\n          };\n        }\n\n        return result;\n      };\n\n      try {\n        behavior.call(self, $window, $document, done);\n      } catch(e) {\n        if (e.type && e.type === 'selector') {\n          done(e.message);\n        } else {\n          throw e;\n        }\n      }\n    });\n  }, line);\n};\n\n/**\n * Shared DSL statements that are useful to all scenarios.\n */\n\n /**\n * Usage:\n *    pause() pauses until you call resume() in the console\n */\nangular.scenario.dsl('pause', function() {\n  return function() {\n    return this.addFuture('pausing for you to resume', function(done) {\n      this.emit('InteractivePause', this.spec, this.step);\n      this.$window.resume = function() { done(); };\n    });\n  };\n});\n\n/**\n * Usage:\n *    sleep(seconds) pauses the test for specified number of seconds\n */\nangular.scenario.dsl('sleep', function() {\n  return function(time) {\n    return this.addFuture('sleep for ' + time + ' seconds', function(done) {\n      this.$window.setTimeout(function() { done(null, time * 1000); }, time * 1000);\n    });\n  };\n});\n\n/**\n * Usage:\n *    browser().navigateTo(url) Loads the url into the frame\n *    browser().navigateTo(url, fn) where fn(url) is called and returns the URL to navigate to\n *    browser().reload() refresh the page (reload the same URL)\n *    browser().window.href() window.location.href\n *    browser().window.path() window.location.pathname\n *    browser().window.search() window.location.search\n *    browser().window.hash() window.location.hash without # prefix\n *    browser().location().url() see ng.$location#url\n *    browser().location().path() see ng.$location#path\n *    browser().location().search() see ng.$location#search\n *    browser().location().hash() see ng.$location#hash\n */\nangular.scenario.dsl('browser', function() {\n  var chain = {};\n\n  chain.navigateTo = function(url, delegate) {\n    var application = this.application;\n    return this.addFuture(\"browser navigate to '\" + url + \"'\", function(done) {\n      if (delegate) {\n        url = delegate.call(this, url);\n      }\n      application.navigateTo(url, function() {\n        done(null, url);\n      }, done);\n    });\n  };\n\n  chain.reload = function() {\n    var application = this.application;\n    return this.addFutureAction('browser reload', function($window, $document, done) {\n      var href = $window.location.href;\n      application.navigateTo(href, function() {\n        done(null, href);\n      }, done);\n    });\n  };\n\n  chain.window = function() {\n    var api = {};\n\n    api.href = function() {\n      return this.addFutureAction('window.location.href', function($window, $document, done) {\n        done(null, $window.location.href);\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('window.location.path', function($window, $document, done) {\n        done(null, $window.location.pathname);\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('window.location.search', function($window, $document, done) {\n        done(null, $window.location.search);\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('window.location.hash', function($window, $document, done) {\n        done(null, $window.location.hash.replace('#', ''));\n      });\n    };\n\n    return api;\n  };\n\n  chain.location = function() {\n    var api = {};\n\n    api.url = function() {\n      return this.addFutureAction('$location.url()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').url());\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('$location.path()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').path());\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('$location.search()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').search());\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('$location.hash()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').hash());\n      });\n    };\n\n    return api;\n  };\n\n  return function() {\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    expect(future).{matcher} where matcher is one of the matchers defined\n *    with angular.scenario.matcher\n *\n * ex. expect(binding(\"name\")).toEqual(\"Elliott\")\n */\nangular.scenario.dsl('expect', function() {\n  var chain = angular.extend({}, angular.scenario.matcher);\n\n  chain.not = function() {\n    this.inverse = true;\n    return chain;\n  };\n\n  return function(future) {\n    this.future = future;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    using(selector, label) scopes the next DSL element selection\n *\n * ex.\n *   using('#foo', \"'Foo' text field\").input('bar')\n */\nangular.scenario.dsl('using', function() {\n  return function(selector, label) {\n    this.selector = _jQuery.trim((this.selector||'') + ' ' + selector);\n    if (angular.isString(label) && label.length) {\n      this.label = label + ' ( ' + this.selector + ' )';\n    } else {\n      this.label = this.selector;\n    }\n    return this.dsl;\n  };\n});\n\n/**\n * Usage:\n *    binding(name) returns the value of the first matching binding\n */\nangular.scenario.dsl('binding', function() {\n  return function(name) {\n    return this.addFutureAction(\"select binding '\" + name + \"'\", function($window, $document, done) {\n      var values = $document.elements().bindings($window.angular.element, name);\n      if (!values.length) {\n        return done(\"Binding selector '\" + name + \"' did not match.\");\n      }\n      done(null, values[0]);\n    });\n  };\n});\n\n/**\n * Usage:\n *    input(name).enter(value) enters value in input with specified name\n *    input(name).check() checks checkbox\n *    input(name).select(value) selects the radio button with specified name/value\n *    input(name).val() returns the value of the input.\n */\nangular.scenario.dsl('input', function() {\n  var chain = {};\n  var supportInputEvent =  'oninput' in document.createElement('div') && msie != 9;\n\n  chain.enter = function(value, event) {\n    return this.addFutureAction(\"input '\" + this.name + \"' enter '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      input.val(value);\n      input.trigger(event || (supportInputEvent ? 'input' : 'change'));\n      done();\n    });\n  };\n\n  chain.check = function() {\n    return this.addFutureAction(\"checkbox '\" + this.name + \"' toggle\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':checkbox');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.select = function(value) {\n    return this.addFutureAction(\"radio button '\" + this.name + \"' toggle '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.\n        elements('[ng\\\\:model=\"$1\"][value=\"$2\"]', this.name, value).filter(':radio');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.val = function() {\n    return this.addFutureAction(\"return input val\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      done(null,input.val());\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n\n/**\n * Usage:\n *    repeater('#products table', 'Product List').count() number of rows\n *    repeater('#products table', 'Product List').row(1) all bindings in row as an array\n *    repeater('#products table', 'Product List').column('product.name') all values across all rows in an array\n */\nangular.scenario.dsl('repeater', function() {\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.column = function(binding) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' column '\" + binding + \"'\", function($window, $document, done) {\n      done(null, $document.elements().bindings($window.angular.element, binding));\n    });\n  };\n\n  chain.row = function(index) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' row '\" + index + \"'\", function($window, $document, done) {\n      var matches = $document.elements().slice(index, index + 1);\n      if (!matches.length)\n        return done('row ' + index + ' out of bounds');\n      done(null, matches.bindings($window.angular.element));\n    });\n  };\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    select(name).option('value') select one option\n *    select(name).options('value1', 'value2', ...) select options from a multi select\n */\nangular.scenario.dsl('select', function() {\n  var chain = {};\n\n  chain.option = function(value) {\n    return this.addFutureAction(\"select '\" + this.name + \"' option '\" + value + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[ng\\\\:model=\"$1\"]', this.name);\n      var option = select.find('option[value=\"' + value + '\"]');\n      if (option.length) {\n        select.val(value);\n      } else {\n        option = select.find('option:contains(\"' + value + '\")');\n        if (option.length) {\n          select.val(option.val());\n        }\n      }\n      select.trigger('change');\n      done();\n    });\n  };\n\n  chain.options = function() {\n    var values = arguments;\n    return this.addFutureAction(\"select '\" + this.name + \"' options '\" + values + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[multiple][ng\\\\:model=\"$1\"]', this.name);\n      select.val(values);\n      select.trigger('change');\n      done();\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    element(selector, label).count() get the number of elements that match selector\n *    element(selector, label).click() clicks an element\n *    element(selector, label).query(fn) executes fn(selectedElements, done)\n *    element(selector, label).{method}() gets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(value) sets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(key) gets the value (as defined by jQuery, ex. attr)\n *    element(selector, label).{method}(key, value) sets the value (as defined by jQuery, ex. attr)\n */\nangular.scenario.dsl('element', function() {\n  var KEY_VALUE_METHODS = ['attr', 'css', 'prop'];\n  var VALUE_METHODS = [\n    'val', 'text', 'html', 'height', 'innerHeight', 'outerHeight', 'width',\n    'innerWidth', 'outerWidth', 'position', 'scrollLeft', 'scrollTop', 'offset'\n  ];\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.click = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' click\", function($window, $document, done) {\n      var elements = $document.elements();\n      var href = elements.attr('href');\n      var eventProcessDefault = elements.trigger('click')[0];\n\n      if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {\n        this.application.navigateTo(href, function() {\n          done();\n        }, done);\n      } else {\n        done();\n      }\n    });\n  };\n\n  chain.query = function(fn) {\n    return this.addFutureAction('element ' + this.label + ' custom query', function($window, $document, done) {\n      fn.call(this, $document.elements(), done);\n    });\n  };\n\n  angular.forEach(KEY_VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(name, value) {\n      var args = arguments,\n          futureName = (args.length == 1)\n              ? \"element '\" + this.label + \"' get \" + methodName + \" '\" + name + \"'\"\n              : \"element '\" + this.label + \"' set \" + methodName + \" '\" + name + \"' to \" + \"'\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  angular.forEach(VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(value) {\n      var args = arguments,\n          futureName = (args.length == 0)\n              ? \"element '\" + this.label + \"' \" + methodName\n              : futureName = \"element '\" + this.label + \"' set \" + methodName + \" to '\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Matchers for implementing specs. Follows the Jasmine spec conventions.\n */\n\nangular.scenario.matcher('toEqual', function(expected) {\n  return angular.equals(this.actual, expected);\n});\n\nangular.scenario.matcher('toBe', function(expected) {\n  return this.actual === expected;\n});\n\nangular.scenario.matcher('toBeDefined', function() {\n  return angular.isDefined(this.actual);\n});\n\nangular.scenario.matcher('toBeTruthy', function() {\n  return this.actual;\n});\n\nangular.scenario.matcher('toBeFalsy', function() {\n  return !this.actual;\n});\n\nangular.scenario.matcher('toMatch', function(expected) {\n  return new RegExp(expected).test(this.actual);\n});\n\nangular.scenario.matcher('toBeNull', function() {\n  return this.actual === null;\n});\n\nangular.scenario.matcher('toContain', function(expected) {\n  return includes(this.actual, expected);\n});\n\nangular.scenario.matcher('toBeLessThan', function(expected) {\n  return this.actual < expected;\n});\n\nangular.scenario.matcher('toBeGreaterThan', function(expected) {\n  return this.actual > expected;\n});\n\n/**\n * User Interface for the Scenario Runner.\n *\n * TODO(esprehn): This should be refactored now that ObjectModel exists\n *  to use angular bindings for the UI.\n */\nangular.scenario.output('html', function(context, runner, model) {\n  var specUiMap = {},\n      lastStepUiMap = {};\n\n  context.append(\n    '<div id=\"header\">' +\n    '  <h1><span class=\"angular\">AngularJS</span>: Scenario Test Runner</h1>' +\n    '  <ul id=\"status-legend\" class=\"status-display\">' +\n    '    <li class=\"status-error\">0 Errors</li>' +\n    '    <li class=\"status-failure\">0 Failures</li>' +\n    '    <li class=\"status-success\">0 Passed</li>' +\n    '  </ul>' +\n    '</div>' +\n    '<div id=\"specs\">' +\n    '  <div class=\"test-children\"></div>' +\n    '</div>'\n  );\n\n  runner.on('InteractivePause', function(spec) {\n    var ui = lastStepUiMap[spec.id];\n    ui.find('.test-title').\n      html('paused... <a href=\"javascript:resume()\">resume</a> when ready.');\n  });\n\n  runner.on('SpecBegin', function(spec) {\n    var ui = findContext(spec);\n    ui.find('> .tests').append(\n      '<li class=\"status-pending test-it\"></li>'\n    );\n    ui = ui.find('> .tests li:last');\n    ui.append(\n      '<div class=\"test-info\">' +\n      '  <p class=\"test-title\">' +\n      '    <span class=\"timer-result\"></span>' +\n      '    <span class=\"test-name\"></span>' +\n      '  </p>' +\n      '</div>' +\n      '<div class=\"scrollpane\">' +\n      '  <ol class=\"test-actions\"></ol>' +\n      '</div>'\n    );\n    ui.find('> .test-info .test-name').text(spec.name);\n    ui.find('> .test-info').click(function() {\n      var scrollpane = ui.find('> .scrollpane');\n      var actions = scrollpane.find('> .test-actions');\n      var name = context.find('> .test-info .test-name');\n      if (actions.find(':visible').length) {\n        actions.hide();\n        name.removeClass('open').addClass('closed');\n      } else {\n        actions.show();\n        scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n        name.removeClass('closed').addClass('open');\n      }\n    });\n\n    specUiMap[spec.id] = ui;\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var ui = specUiMap[spec.id];\n    ui.append('<pre></pre>');\n    ui.find('> pre').text(formatException(error));\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    ui.removeClass('status-pending');\n    ui.addClass('status-' + spec.status);\n    ui.find(\"> .test-info .timer-result\").text(spec.duration + \"ms\");\n    if (spec.status === 'success') {\n      ui.find('> .test-info .test-name').addClass('closed');\n      ui.find('> .scrollpane .test-actions').hide();\n    }\n    updateTotals(spec.status);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    ui.find('> .scrollpane .test-actions').append('<li class=\"status-pending\"></li>');\n    var stepUi = lastStepUiMap[spec.id] = ui.find('> .scrollpane .test-actions li:last');\n    stepUi.append(\n      '<div class=\"timer-result\"></div>' +\n      '<div class=\"test-title\"></div>'\n    );\n    stepUi.find('> .test-title').text(step.name);\n    var scrollpane = stepUi.parents('.scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepEnd', function(spec, step) {\n    var stepUi = lastStepUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    stepUi.find('.timer-result').text(step.duration + 'ms');\n    stepUi.removeClass('status-pending');\n    stepUi.addClass('status-' + step.status);\n    var scrollpane = specUiMap[spec.id].find('> .scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  /**\n   * Finds the context of a spec block defined by the passed definition.\n   *\n   * @param {Object} The definition created by the Describe object.\n   */\n  function findContext(spec) {\n    var currentContext = context.find('#specs');\n    angular.forEach(model.getDefinitionPath(spec), function(defn) {\n      var id = 'describe-' + defn.id;\n      if (!context.find('#' + id).length) {\n        currentContext.find('> .test-children').append(\n          '<div class=\"test-describe\" id=\"' + id + '\">' +\n          '  <h2></h2>' +\n          '  <div class=\"test-children\"></div>' +\n          '  <ul class=\"tests\"></ul>' +\n          '</div>'\n        );\n        context.find('#' + id).find('> h2').text('describe: ' + defn.name);\n      }\n      currentContext = context.find('#' + id);\n    });\n    return context.find('#describe-' + spec.definition.id);\n  }\n\n  /**\n   * Updates the test counter for the status.\n   *\n   * @param {string} the status.\n   */\n  function updateTotals(status) {\n    var legend = context.find('#status-legend .status-' + status);\n    var parts = legend.text().split(' ');\n    var value = (parts[0] * 1) + 1;\n    legend.text(value + ' ' + parts[1]);\n  }\n\n  /**\n   * Add an error to a step.\n   *\n   * @param {Object} The JQuery wrapped context\n   * @param {function()} fn() that should return the file/line number of the error\n   * @param {Object} the error.\n   */\n  function addError(context, line, error) {\n    context.find('.test-title').append('<pre></pre>');\n    var message = _jQuery.trim(line() + '\\n\\n' + formatException(error));\n    context.find('.test-title pre:last').text(message);\n  }\n});\n\n/**\n * Generates JSON output into a context.\n */\nangular.scenario.output('json', function(context, runner, model) {\n  model.on('RunnerEnd', function() {\n    context.text(angular.toJson(model.value));\n  });\n});\n\n/**\n * Generates XML output into a context.\n */\nangular.scenario.output('xml', function(context, runner, model) {\n  var $ = function(args) {return new context.init(args);};\n  model.on('RunnerEnd', function() {\n    var scenario = $('<scenario></scenario>');\n    context.append(scenario);\n    serializeXml(scenario, model.value);\n  });\n\n  /**\n   * Convert the tree into XML.\n   *\n   * @param {Object} context jQuery context to add the XML to.\n   * @param {Object} tree node to serialize\n   */\n  function serializeXml(context, tree) {\n     angular.forEach(tree.children, function(child) {\n       var describeContext = $('<describe></describe>');\n       describeContext.attr('id', child.id);\n       describeContext.attr('name', child.name);\n       context.append(describeContext);\n       serializeXml(describeContext, child);\n     });\n     var its = $('<its></its>');\n     context.append(its);\n     angular.forEach(tree.specs, function(spec) {\n       var it = $('<it></it>');\n       it.attr('id', spec.id);\n       it.attr('name', spec.name);\n       it.attr('duration', spec.duration);\n       it.attr('status', spec.status);\n       its.append(it);\n       angular.forEach(spec.steps, function(step) {\n         var stepContext = $('<step></step>');\n         stepContext.attr('name', step.name);\n         stepContext.attr('duration', step.duration);\n         stepContext.attr('status', step.status);\n         it.append(stepContext);\n         if (step.error) {\n           var error = $('<error></error>');\n           stepContext.append(error);\n           error.text(formatException(stepContext.error));\n         }\n       });\n     });\n   }\n});\n\n/**\n * Creates a global value $result with the result of the runner.\n */\nangular.scenario.output('object', function(context, runner, model) {\n  runner.$window.$result = model.value;\n});\nbindJQuery();\npublishExternalAPI(angular);\n\nvar $runner = new angular.scenario.Runner(window),\n    scripts = document.getElementsByTagName('script'),\n    script = scripts[scripts.length - 1],\n    config = {};\n\nangular.forEach(script.attributes, function(attr) {\n  var match = attr.name.match(/ng[:\\-](.*)/);\n  if (match) {\n    config[match[1]] = attr.value || true;\n  }\n});\n\nif (config.autotest) {\n  JQLite(document).ready(function() {\n    angular.scenario.setUpAndRun(config);\n  });\n}\n})(window, document);\n\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n\\n[ng\\\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\\n.ng-cloak, .x-ng-cloak {\\n  display: none;\\n}\\n\\nng\\\\:form {\\n  display: block;\\n}\\n</style>');\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n/* CSS Document */\\n\\n/** Structure */\\nbody {\\n  font-family: Arial, sans-serif;\\n  margin: 0;\\n  font-size: 14px;\\n}\\n\\n#system-error {\\n  font-size: 1.5em;\\n  text-align: center;\\n}\\n\\n#json, #xml {\\n  display: none;\\n}\\n\\n#header {\\n  position: fixed;\\n  width: 100%;\\n}\\n\\n#specs {\\n  padding-top: 50px;\\n}\\n\\n#header .angular {\\n  font-family: Courier New, monospace;\\n  font-weight: bold;\\n}\\n\\n#header h1 {\\n  font-weight: normal;\\n  float: left;\\n  font-size: 30px;\\n  line-height: 30px;\\n  margin: 0;\\n  padding: 10px 10px;\\n  height: 30px;\\n}\\n\\n#application h2,\\n#specs h2 {\\n  margin: 0;\\n  padding: 0.5em;\\n  font-size: 1.1em;\\n}\\n\\n#status-legend {\\n  margin-top: 10px;\\n  margin-right: 10px;\\n}\\n\\n#header,\\n#application,\\n.test-info,\\n.test-actions li {\\n  overflow: hidden;\\n}\\n\\n#application {\\n  margin: 10px;\\n}\\n\\n#application iframe {\\n  width: 100%;\\n  height: 758px;\\n}\\n\\n#application .popout {\\n  float: right;\\n}\\n\\n#application iframe {\\n  border: none;\\n}\\n\\n.tests li,\\n.test-actions li,\\n.test-it li,\\n.test-it ol,\\n.status-display {\\n  list-style-type: none;\\n}\\n\\n.tests,\\n.test-it ol,\\n.status-display {\\n  margin: 0;\\n  padding: 0;\\n}\\n\\n.test-info {\\n  margin-left: 1em;\\n  margin-top: 0.5em;\\n  border-radius: 8px 0 0 8px;\\n  -webkit-border-radius: 8px 0 0 8px;\\n  -moz-border-radius: 8px 0 0 8px;\\n  cursor: pointer;\\n}\\n\\n.test-info:hover .test-name {\\n  text-decoration: underline;\\n}\\n\\n.test-info .closed:before {\\n  content: \\'\\\\25b8\\\\00A0\\';\\n}\\n\\n.test-info .open:before {\\n  content: \\'\\\\25be\\\\00A0\\';\\n  font-weight: bold;\\n}\\n\\n.test-it ol {\\n  margin-left: 2.5em;\\n}\\n\\n.status-display,\\n.status-display li {\\n  float: right;\\n}\\n\\n.status-display li {\\n  padding: 5px 10px;\\n}\\n\\n.timer-result,\\n.test-title {\\n  display: inline-block;\\n  margin: 0;\\n  padding: 4px;\\n}\\n\\n.test-actions .test-title,\\n.test-actions .test-result {\\n  display: table-cell;\\n  padding-left: 0.5em;\\n  padding-right: 0.5em;\\n}\\n\\n.test-actions {\\n  display: table;\\n}\\n\\n.test-actions li {\\n  display: table-row;\\n}\\n\\n.timer-result {\\n  width: 4em;\\n  padding: 0 10px;\\n  text-align: right;\\n  font-family: monospace;\\n}\\n\\n.test-it pre,\\n.test-actions pre {\\n  clear: left;\\n  color: black;\\n  margin-left: 6em;\\n}\\n\\n.test-describe {\\n  padding-bottom: 0.5em;\\n}\\n\\n.test-describe .test-describe {\\n  margin: 5px 5px 10px 2em;\\n}\\n\\n.test-actions .status-pending .test-title:before {\\n  content: \\'\\\\00bb\\\\00A0\\';\\n}\\n\\n.scrollpane {\\n   max-height: 20em;\\n   overflow: auto;\\n}\\n\\n/** Colors */\\n\\n#header {\\n  background-color: #F2C200;\\n}\\n\\n#specs h2 {\\n  border-top: 2px solid #BABAD1;\\n}\\n\\n#specs h2,\\n#application h2 {\\n  background-color: #efefef;\\n}\\n\\n#application {\\n  border: 1px solid #BABAD1;\\n}\\n\\n.test-describe .test-describe {\\n  border-left: 1px solid #BABAD1;\\n  border-right: 1px solid #BABAD1;\\n  border-bottom: 1px solid #BABAD1;\\n}\\n\\n.status-display {\\n  border: 1px solid #777;\\n}\\n\\n.status-display .status-pending,\\n.status-pending .test-info {\\n  background-color: #F9EEBC;\\n}\\n\\n.status-display .status-success,\\n.status-success .test-info {\\n  background-color: #B1D7A1;\\n}\\n\\n.status-display .status-failure,\\n.status-failure .test-info {\\n  background-color: #FF8286;\\n}\\n\\n.status-display .status-error,\\n.status-error .test-info {\\n  background-color: black;\\n  color: white;\\n}\\n\\n.test-actions .status-success .test-title {\\n  color: #30B30A;\\n}\\n\\n.test-actions .status-failure .test-title {\\n  color: #DF0000;\\n}\\n\\n.test-actions .status-error .test-title {\\n  color: black;\\n}\\n\\n.test-actions .timer-result {\\n  color: #888;\\n}\\n</style>');"
  },
  {
    "path": "chapter3/recipe8/test/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter3/recipe8/test/lib/jasmine-jquery.js",
    "content": "var readFixtures = function() {\n  return jasmine.getFixtures().proxyCallTo_('read', arguments)\n}\n\nvar preloadFixtures = function() {\n  jasmine.getFixtures().proxyCallTo_('preload', arguments)\n}\n\nvar loadFixtures = function() {\n  jasmine.getFixtures().proxyCallTo_('load', arguments)\n}\n\nvar appendLoadFixtures = function() {\n  jasmine.getFixtures().proxyCallTo_('appendLoad', arguments)\n}\n\nvar setFixtures = function(html) {\n  jasmine.getFixtures().proxyCallTo_('set', arguments)\n}\n\nvar appendSetFixtures = function() {\n  jasmine.getFixtures().proxyCallTo_('appendSet', arguments)\n}\n\nvar sandbox = function(attributes) {\n  return jasmine.getFixtures().sandbox(attributes)\n}\n\nvar spyOnEvent = function(selector, eventName) {\n  return jasmine.JQuery.events.spyOn(selector, eventName)\n}\n\nvar preloadStyleFixtures = function() {\n  jasmine.getStyleFixtures().proxyCallTo_('preload', arguments)\n}\n\nvar loadStyleFixtures = function() {\n  jasmine.getStyleFixtures().proxyCallTo_('load', arguments)\n}\n\nvar appendLoadStyleFixtures = function() {\n  jasmine.getStyleFixtures().proxyCallTo_('appendLoad', arguments)\n}\n\nvar setStyleFixtures = function(html) {\n  jasmine.getStyleFixtures().proxyCallTo_('set', arguments)\n}\n\nvar appendSetStyleFixtures = function(html) {\n  jasmine.getStyleFixtures().proxyCallTo_('appendSet', arguments)\n}\n\nvar loadJSONFixtures = function() {\n  return jasmine.getJSONFixtures().proxyCallTo_('load', arguments)\n}\n\nvar getJSONFixture = function(url) {\n  return jasmine.getJSONFixtures().proxyCallTo_('read', arguments)[url]\n}\n\njasmine.spiedEventsKey = function (selector, eventName) {\n  return [$(selector).selector, eventName].toString()\n}\n\njasmine.getFixtures = function() {\n  return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures()\n}\n\njasmine.getStyleFixtures = function() {\n  return jasmine.currentStyleFixtures_ = jasmine.currentStyleFixtures_ || new jasmine.StyleFixtures()\n}\n\njasmine.Fixtures = function() {\n  this.containerId = 'jasmine-fixtures'\n  this.fixturesCache_ = {}\n  this.fixturesPath = 'spec/javascripts/fixtures'\n}\n\njasmine.Fixtures.prototype.set = function(html) {\n  this.cleanUp()\n  this.createContainer_(html)\n}\n\njasmine.Fixtures.prototype.appendSet= function(html) {\n  this.addToContainer_(html)\n}\n\njasmine.Fixtures.prototype.preload = function() {\n  this.read.apply(this, arguments)\n}\n\njasmine.Fixtures.prototype.load = function() {\n  this.cleanUp()\n  this.createContainer_(this.read.apply(this, arguments))\n}\n\njasmine.Fixtures.prototype.appendLoad = function() {\n  this.addToContainer_(this.read.apply(this, arguments))\n}\n\njasmine.Fixtures.prototype.read = function() {\n  var htmlChunks = []\n\n  var fixtureUrls = arguments\n  for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {\n    htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex]))\n  }\n\n  return htmlChunks.join('')\n}\n\njasmine.Fixtures.prototype.clearCache = function() {\n  this.fixturesCache_ = {}\n}\n\njasmine.Fixtures.prototype.cleanUp = function() {\n  $('#' + this.containerId).remove()\n}\n\njasmine.Fixtures.prototype.sandbox = function(attributes) {\n  var attributesToSet = attributes || {}\n  return $('<div id=\"sandbox\" />').attr(attributesToSet)\n}\n\njasmine.Fixtures.prototype.createContainer_ = function(html) {\n  var container\n  if(html instanceof $) {\n    container = $('<div id=\"' + this.containerId + '\" />')\n    container.html(html)\n  } else {\n    container = '<div id=\"' + this.containerId + '\">' + html + '</div>'\n  }\n  $(document.body).append(container)\n}\n\njasmine.Fixtures.prototype.addToContainer_ = function(html){\n  var container = $(document.body).find('#'+this.containerId).append(html)\n  if(!container.length){\n    this.createContainer_(html)\n  }\n}\n\njasmine.Fixtures.prototype.getFixtureHtml_ = function(url) {\n  if (typeof this.fixturesCache_[url] === 'undefined') {\n    this.loadFixtureIntoCache_(url)\n  }\n  return this.fixturesCache_[url]\n}\n\njasmine.Fixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) {\n  var url = this.makeFixtureUrl_(relativeUrl)\n  var request = $.ajax({\n    type: \"GET\",\n    url: url + \"?\" + new Date().getTime(),\n    async: false\n  })\n  this.fixturesCache_[relativeUrl] = request.responseText\n}\n\njasmine.Fixtures.prototype.makeFixtureUrl_ = function(relativeUrl){\n  return this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl\n}\n\njasmine.Fixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) {\n  return this[methodName].apply(this, passedArguments)\n}\n\n\njasmine.StyleFixtures = function() {\n  this.fixturesCache_ = {}\n  this.fixturesNodes_ = []\n  this.fixturesPath = 'spec/javascripts/fixtures'\n}\n\njasmine.StyleFixtures.prototype.set = function(css) {\n  this.cleanUp()\n  this.createStyle_(css)\n}\n\njasmine.StyleFixtures.prototype.appendSet = function(css) {\n  this.createStyle_(css)\n}\n\njasmine.StyleFixtures.prototype.preload = function() {\n  this.read_.apply(this, arguments)\n}\n\njasmine.StyleFixtures.prototype.load = function() {\n  this.cleanUp()\n  this.createStyle_(this.read_.apply(this, arguments))\n}\n\njasmine.StyleFixtures.prototype.appendLoad = function() {\n  this.createStyle_(this.read_.apply(this, arguments))\n}\n\njasmine.StyleFixtures.prototype.cleanUp = function() {\n  while(this.fixturesNodes_.length) {\n    this.fixturesNodes_.pop().remove()\n  }\n}\n\njasmine.StyleFixtures.prototype.createStyle_ = function(html) {\n  var styleText = $('<div></div>').html(html).text(),\n    style = $('<style>' + styleText + '</style>')\n\n  this.fixturesNodes_.push(style)\n\n  $('head').append(style)\n}\n\njasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache\n\njasmine.StyleFixtures.prototype.read_ = jasmine.Fixtures.prototype.read\n\njasmine.StyleFixtures.prototype.getFixtureHtml_ = jasmine.Fixtures.prototype.getFixtureHtml_\n\njasmine.StyleFixtures.prototype.loadFixtureIntoCache_ = jasmine.Fixtures.prototype.loadFixtureIntoCache_\n\njasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.makeFixtureUrl_\n\njasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_\n\njasmine.getJSONFixtures = function() {\n  return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures()\n}\n\njasmine.JSONFixtures = function() {\n  this.fixturesCache_ = {}\n  this.fixturesPath = 'spec/javascripts/fixtures/json'\n}\n\njasmine.JSONFixtures.prototype.load = function() {\n  this.read.apply(this, arguments)\n  return this.fixturesCache_\n}\n\njasmine.JSONFixtures.prototype.read = function() {\n  var fixtureUrls = arguments\n  for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {\n    this.getFixtureData_(fixtureUrls[urlIndex])\n  }\n  return this.fixturesCache_\n}\n\njasmine.JSONFixtures.prototype.clearCache = function() {\n  this.fixturesCache_ = {}\n}\n\njasmine.JSONFixtures.prototype.getFixtureData_ = function(url) {\n  this.loadFixtureIntoCache_(url)\n  return this.fixturesCache_[url]\n}\n\njasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) {\n  var self = this\n  var url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl\n  $.ajax({\n    async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded\n    cache: false,\n    dataType: 'json',\n    url: url,\n    success: function(data) {\n      self.fixturesCache_[relativeUrl] = data\n    },\n    fail: function(jqXHR, status, errorThrown) {\n        throw Error('JSONFixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + errorThrown.message + ')')\n    }\n  })\n}\n\njasmine.JSONFixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) {\n  return this[methodName].apply(this, passedArguments)\n}\n\njasmine.JQuery = function() {}\n\njasmine.JQuery.browserTagCaseIndependentHtml = function(html) {\n  return $('<div/>').append(html).html()\n}\n\njasmine.JQuery.elementToString = function(element) {\n  var domEl = $(element).get(0)\n  if (domEl == undefined || domEl.cloneNode)\n    return $('<div />').append($(element).clone()).html()\n  else\n    return element.toString()\n}\n\njasmine.JQuery.matchersClass = {}\n\n!function(namespace) {\n  var data = {\n    spiedEvents: {},\n    handlers:    []\n  }\n\n  namespace.events = {\n    spyOn: function(selector, eventName) {\n      var handler = function(e) {\n        data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = e\n      }\n      $(selector).bind(eventName, handler)\n      data.handlers.push(handler)\n      return {\n        selector: selector,\n        eventName: eventName,\n        handler: handler,\n        reset: function(){\n          delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]\n        }\n      }\n    },\n\n    wasTriggered: function(selector, eventName) {\n      return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)])\n    },\n\n    wasPrevented: function(selector, eventName) {\n      var e;\n      return (e = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]) && e.isDefaultPrevented()\n    },\n\n    cleanUp: function() {\n      data.spiedEvents = {}\n      data.handlers    = []\n    }\n  }\n}(jasmine.JQuery)\n\n!function(){\n  var jQueryMatchers = {\n    toHaveClass: function(className) {\n      return this.actual.hasClass(className)\n    },\n\n    toHaveCss: function(css){\n      for (var prop in css){\n        if (this.actual.css(prop) !== css[prop]) return false\n      }\n      return true\n    },\n\n    toBeVisible: function() {\n      return this.actual.is(':visible')\n    },\n\n    toBeHidden: function() {\n      return this.actual.is(':hidden')\n    },\n\n    toBeSelected: function() {\n      return this.actual.is(':selected')\n    },\n\n    toBeChecked: function() {\n      return this.actual.is(':checked')\n    },\n\n    toBeEmpty: function() {\n      return this.actual.is(':empty')\n    },\n\n    toExist: function() {\n      return $(document).find(this.actual).length\n    },\n\n    toHaveLength: function(length) {\n      return this.actual.length === length\n    },\n\n    toHaveAttr: function(attributeName, expectedAttributeValue) {\n      return hasProperty(this.actual.attr(attributeName), expectedAttributeValue)\n    },\n\n    toHaveProp: function(propertyName, expectedPropertyValue) {\n      return hasProperty(this.actual.prop(propertyName), expectedPropertyValue)\n    },\n\n    toHaveId: function(id) {\n      return this.actual.attr('id') == id\n    },\n\n    toHaveHtml: function(html) {\n      return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html)\n    },\n\n    toContainHtml: function(html){\n      var actualHtml = this.actual.html()\n      var expectedHtml = jasmine.JQuery.browserTagCaseIndependentHtml(html)\n      return (actualHtml.indexOf(expectedHtml) >= 0)\n    },\n\n    toHaveText: function(text) {\n      var trimmedText = $.trim(this.actual.text())\n      if (text && $.isFunction(text.test)) {\n        return text.test(trimmedText)\n      } else {\n        return trimmedText == text\n      }\n    },\n\n    toHaveValue: function(value) {\n      return this.actual.val() === value\n    },\n\n    toHaveData: function(key, expectedValue) {\n      return hasProperty(this.actual.data(key), expectedValue)\n    },\n\n    toBe: function(selector) {\n      return this.actual.is(selector)\n    },\n\n    toContain: function(selector) {\n      return this.actual.find(selector).length\n    },\n\n    toBeDisabled: function(selector){\n      return this.actual.is(':disabled')\n    },\n\n    toBeFocused: function(selector) {\n      return this.actual[0] === this.actual[0].ownerDocument.activeElement\n    },\n\n    toHandle: function(event) {\n\n      var events = $._data(this.actual.get(0), \"events\")\n\n      if(!events || !event || typeof event !== \"string\") {\n        return false\n      }\n\n      var namespaces = event.split(\".\")\n      var eventType = namespaces.shift()\n      var sortedNamespaces = namespaces.slice(0).sort()\n      var namespaceRegExp = new RegExp(\"(^|\\\\.)\" + sortedNamespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\")\n\n      if(events[eventType] && namespaces.length) {\n        for(var i = 0; i < events[eventType].length; i++) {\n          var namespace = events[eventType][i].namespace\n          if(namespaceRegExp.test(namespace)) {\n            return true\n          }\n        }\n      } else {\n        return events[eventType] && events[eventType].length > 0\n      }\n    },\n\n    // tests the existence of a specific event binding + handler\n    toHandleWith: function(eventName, eventHandler) {\n      var stack = $._data(this.actual.get(0), \"events\")[eventName]\n      for (var i = 0; i < stack.length; i++) {\n        if (stack[i].handler == eventHandler) return true\n      }\n      return false\n    }\n  }\n\n  var hasProperty = function(actualValue, expectedValue) {\n    if (expectedValue === undefined) return actualValue !== undefined\n    return actualValue == expectedValue\n  }\n\n  var bindMatcher = function(methodName) {\n    var builtInMatcher = jasmine.Matchers.prototype[methodName]\n\n    jasmine.JQuery.matchersClass[methodName] = function() {\n      if (this.actual\n        && (this.actual instanceof $\n          || jasmine.isDomNode(this.actual))) {\n            this.actual = $(this.actual)\n            var result = jQueryMatchers[methodName].apply(this, arguments)\n            var element\n            if (this.actual.get && (element = this.actual.get()[0]) && !$.isWindow(element) && element.tagName !== \"HTML\")\n              this.actual = jasmine.JQuery.elementToString(this.actual)\n            return result\n          }\n\n          if (builtInMatcher) {\n            return builtInMatcher.apply(this, arguments)\n          }\n\n          return false\n    }\n  }\n\n  for(var methodName in jQueryMatchers) {\n    bindMatcher(methodName)\n  }\n}()\n\nbeforeEach(function() {\n  this.addMatchers(jasmine.JQuery.matchersClass)\n  this.addMatchers({\n    toHaveBeenTriggeredOn: function(selector) {\n      this.message = function() {\n        return [\n          \"Expected event \" + this.actual + \" to have been triggered on \" + selector,\n          \"Expected event \" + this.actual + \" not to have been triggered on \" + selector\n        ]\n      }\n      return jasmine.JQuery.events.wasTriggered(selector, this.actual)\n    }\n  })\n  this.addMatchers({\n    toHaveBeenTriggered: function(){\n      var eventName = this.actual.eventName,\n          selector = this.actual.selector\n      this.message = function() {\n        return [\n          \"Expected event \" + eventName + \" to have been triggered on \" + selector,\n          \"Expected event \" + eventName + \" not to have been triggered on \" + selector\n        ]\n      }\n      return jasmine.JQuery.events.wasTriggered(selector, eventName)\n     }\n  })\n  this.addMatchers({\n    toHaveBeenPreventedOn: function(selector) {\n      this.message = function() {\n        return [\n          \"Expected event \" + this.actual + \" to have been prevented on \" + selector,\n          \"Expected event \" + this.actual + \" not to have been prevented on \" + selector\n        ]\n      }\n      return jasmine.JQuery.events.wasPrevented(selector, this.actual)\n    }\n  })\n  this.addMatchers({\n    toHaveBeenPrevented: function() {\n      var eventName = this.actual.eventName,\n          selector = this.actual.selector\n      this.message = function() {\n        return [\n          \"Expected event \" + eventName + \" to have been prevented on \" + selector,\n          \"Expected event \" + eventName + \" not to have been prevented on \" + selector\n        ]\n      }\n      return jasmine.JQuery.events.wasPrevented(selector, eventName)\n    }\n  })\n})\n\nafterEach(function() {\n  jasmine.getFixtures().cleanUp()\n  jasmine.getStyleFixtures().cleanUp()\n  jasmine.JQuery.events.cleanUp()\n})"
  },
  {
    "path": "chapter3/recipe8/test/unit/directivesSpec.js",
    "content": "describe('MyApp Tabs', function() {\n  var elm, scope;\n\n  beforeEach(module('MyApp'));\n\n  beforeEach(inject(function($rootScope, $compile) {\n    elm = angular.element(\n      '<div>' +\n        '<tabs>' +\n          '<pane title=\"First Tab\">' +\n            'First content is {{first}}' +\n          '</pane>' +\n          '<pane title=\"Second Tab\">' +\n            'Second content is {{second}}' +\n          '</pane>' +\n        '</tabs>' +\n      '</div>');\n\n    scope = $rootScope;\n    $compile(elm)(scope);\n    scope.$digest();\n  }));\n\n\n  it('should create clickable titles', function() {\n    console.log(elm.find('ul.nav-tabs'));\n    var titles = elm.find('ul.nav-tabs li a');\n\n    expect(titles.length).toBe(2);\n    expect(titles.eq(0).text()).toBe('First Tab');\n    expect(titles.eq(1).text()).toBe('Second Tab');\n  });\n\n  it('should set active class on title', function() {\n    var titles = elm.find('ul.nav-tabs li');\n\n    expect(titles.eq(0)).toHaveClass('active');\n    expect(titles.eq(1)).not.toHaveClass('active');\n  });\n\n  it('should change active pane when title clicked', function() {\n    var titles = elm.find('ul.nav-tabs li');\n    var contents = elm.find('div.tab-content div.tab-pane');\n\n    titles.eq(1).find('a').click();\n\n    expect(titles.eq(0)).not.toHaveClass('active');\n    expect(titles.eq(1)).toHaveClass('active');\n\n    expect(contents.eq(0)).not.toHaveClass('active');\n    expect(contents.eq(1)).toHaveClass('active');\n  });\n});"
  },
  {
    "path": "chapter4/recipe1/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter4/recipe1/index.html",
    "content": "<html>\n  <head>\n    <meta charset='utf-8'>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/angular-locale_de.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app>\n    <input type=\"text\" ng-model=\"amount\" placeholder=\"Enter amount\"/>\n    <p>Default Currency: {{ amount | currency }}</p>\n    <p>Custom Currency: {{ amount | currency: \"Euro €\" }}</p>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter4/recipe1/js/angular-locale_de.js",
    "content": "angular.module(\"ngLocale\", [], [\"$provide\", function($provide) {\nvar PLURAL_CATEGORY = {ZERO: \"zero\", ONE: \"one\", TWO: \"two\", FEW: \"few\", MANY: \"many\", OTHER: \"other\"};\n$provide.value(\"$locale\", {\"DATETIME_FORMATS\":{\"MONTH\":[\"Januar\",\"Februar\",\"März\",\"April\",\"Mai\",\"Juni\",\"Juli\",\"August\",\"September\",\"Oktober\",\"November\",\"Dezember\"],\"SHORTMONTH\":[\"Jan\",\"Feb\",\"Mär\",\"Apr\",\"Mai\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Okt\",\"Nov\",\"Dez\"],\"DAY\":[\"Sonntag\",\"Montag\",\"Dienstag\",\"Mittwoch\",\"Donnerstag\",\"Freitag\",\"Samstag\"],\"SHORTDAY\":[\"So.\",\"Mo.\",\"Di.\",\"Mi.\",\"Do.\",\"Fr.\",\"Sa.\"],\"AMPMS\":[\"vorm.\",\"nachm.\"],\"medium\":\"dd.MM.yyyy HH:mm:ss\",\"short\":\"dd.MM.yy HH:mm\",\"fullDate\":\"EEEE, d. MMMM y\",\"longDate\":\"d. MMMM y\",\"mediumDate\":\"dd.MM.yyyy\",\"shortDate\":\"dd.MM.yy\",\"mediumTime\":\"HH:mm:ss\",\"shortTime\":\"HH:mm\"},\"NUMBER_FORMATS\":{\"DECIMAL_SEP\":\",\",\"GROUP_SEP\":\".\",\"PATTERNS\":[{\"minInt\":1,\"minFrac\":0,\"macFrac\":0,\"posPre\":\"\",\"posSuf\":\"\",\"negPre\":\"-\",\"negSuf\":\"\",\"gSize\":3,\"lgSize\":3,\"maxFrac\":3},{\"minInt\":1,\"minFrac\":2,\"macFrac\":0,\"posPre\":\"\",\"posSuf\":\" \\u00A4\",\"negPre\":\"-\",\"negSuf\":\" \\u00A4\",\"gSize\":3,\"lgSize\":3,\"maxFrac\":2}],\"CURRENCY_SYM\":\"€\"},\"pluralCat\":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},\"id\":\"de\"});\n}]);"
  },
  {
    "path": "chapter4/recipe1/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter4/recipe2/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter4/recipe2/index.html",
    "content": "<html>\n  <head>\n    <meta charset='utf-8'>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <input type=\"text\" ng-model=\"text\" placeholder=\"Enter text\"/>\n    <p>Input: {{ text }}</p>\n    <p>Filtered input: {{ text | reverse }}</p>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter4/recipe2/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter4/recipe2/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.filter(\"reverse\", function() {\n  return function(input) {\n    var result = \"\";\n    input = input || \"\";\n    for (var i=0; i<input.length; i++) {\n      result = input.charAt(i) + result;\n    }\n    return result;\n  };\n});"
  },
  {
    "path": "chapter4/recipe3/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter4/recipe3/index.html",
    "content": "<html>\n  <head>\n    <meta charset='utf-8'>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <ul ng-init=\"names = ['Peter', 'Anton', 'John']\">\n      <li ng-repeat=\"name in names | exclude:'Peter'\">\n        <span>{{name}}</span>\n      </li>\n    </ul>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter4/recipe3/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter4/recipe3/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.filter(\"exclude\", function() {\n  return function(input, exclude) {\n    var result = [];\n    for (var i=0; i<input.length; i++) {\n      if (input[i] !== exclude) {\n        result.push(input[i]);\n      }\n    }\n\n    return result;\n  };\n});"
  },
  {
    "path": "chapter4/recipe4/README.md",
    "content": "# angular-seed — the seed for AngularJS apps\n\nThis project is an application skeleton for a typical [AngularJS](http://angularjs.org/) web app.\nYou can use it to quickly bootstrap your angular webapp projects and dev environment for these\nprojects.\n\nThe seed contains AngularJS libraries, test libraries and a bunch of scripts all preconfigured for\ninstant web development gratification. Just clone the repo (or download the zip/tarball), start up\nour (or yours) webserver and you are ready to develop and test your application.\n\nThe seed app doesn't do much, just shows how to wire two controllers and views together. You can\ncheck it out by opening app/index.html in your browser (might not work file `file://` scheme in\ncertain browsers, see note below).\n\n_Note: While angular is client-side-only technology and it's possible to create angular webapps that\ndon't require a backend server at all, we recommend hosting the project files using a local\nwebserver during development to avoid issues with security restrictions (sandbox) in browsers. The\nsandbox implementation varies between browsers, but quite often prevents things like cookies, xhr,\netc to function properly when an html page is opened via `file://` scheme instead of `http://`._\n\n\n## How to use angular-seed\n\nClone the angular-seed repository and start hacking...\n\n\n### Running the app during development\n\nYou can pick one of these options:\n\n* serve this repository with your webserver\n* install node.js and run `scripts/web-server.js`\n\nThen navigate your browser to `http://localhost:<port>/app/index.html` to see the app running in\nyour browser.\n\n\n### Running the app in production\n\nThis really depends on how complex is your app and the overall infrastructure of your system, but\nthe general rule is that all you need in production are all the files under the `app/` directory.\nEverything else should be omitted.\n\nAngular apps are really just a bunch of static html, css and js files that just need to be hosted\nsomewhere, where they can be accessed by browsers.\n\nIf your Angular app is talking to the backend server via xhr or other means, you need to figure\nout what is the best way to host the static files to comply with the same origin policy if\napplicable. Usually this is done by hosting the files by the backend server or through\nreverse-proxying the backend server(s) and a webserver(s).\n\n\n### Running unit tests\n\nWe recommend using [jasmine](http://pivotal.github.com/jasmine/) and\n[Testacular](http://vojtajina.github.com/testacular/) for your unit tests/specs, but you are free\nto use whatever works for you.\n\nRequires [node.js](http://nodejs.org/), Testacular (`sudo npm install -g testacular`) and a local\nor remote browser.\n\n* start `scripts/test.sh` (on windows: `scripts\\test.bat`)\n  * a browser will start and connect to the Testacular server (Chrome is default browser, others can be captured by loading the same url as the one in Chrome or by changing the `config/testacular.conf.js` file)\n* to run or re-run tests just change any of your source or test javascript files\n\n\n### End to end testing\n\nAngular ships with a baked-in end-to-end test runner that understands angular, your app and allows\nyou to write your tests with jasmine-like BDD syntax.\n\nRequires a webserver, node.js + `./scripts/web-server.js` or your backend server that hosts the angular static files.\n\nCheck out the\n[end-to-end runner's documentation](http://docs.angularjs.org/guide/dev_guide.e2e-testing) for more\ninfo.\n\n* create your end-to-end tests in `test/e2e/scenarios.js`\n* serve your project directory with your http/backend server or node.js + `scripts/web-server.js`\n* to run do one of:\n  * open `http://localhost:port/test/e2e/runner.html` in your browser\n  * run the tests from console with [Testacular](vojtajina.github.com/testacular) via\n    `scripts/e2e-test.sh` or `script/e2e-test.bat`\n\n\n### Receiving updates from upstream\n\nWhen we upgrade angular-seed's repo with newer angular or testing library code, you can just\nfetch the changes and merge them into your project with git.\n\n\n## Directory Layout\n\n    app/                --> all of the files to be used in production\n      css/              --> css files\n        app.css         --> default stylesheet\n      img/              --> image files\n      index.html        --> app layout file (the main html template file of the app)\n      index-async.html  --> just like index.html, but loads js files asynchronously\n      js/               --> javascript files\n        app.js          --> application\n        controllers.js  --> application controllers\n        directives.js   --> application directives\n        filters.js      --> custom angular filters\n        services.js     --> custom angular services\n      lib/              --> angular and 3rd party javascript libraries\n        angular/\n          angular.js        --> the latest angular js\n          angular.min.js    --> the latest minified angular js\n          angular-*.js      --> angular add-on modules\n          version.txt       --> version number\n      partials/             --> angular view partials (partial html templates)\n        partial1.html\n        partial2.html\n\n    config/testacular.conf.js        --> config file for running unit tests with Testacular\n    config/testacular-e2e.conf.js    --> config file for running e2e tests with Testacular\n\n    scripts/            --> handy shell/js/ruby scripts\n      e2e-test.sh       --> runs end-to-end tests with Testacular (*nix)\n      e2e-test.bat      --> runs end-to-end tests with Testacular (windows)\n      test.bat          --> autotests unit tests with Testacular (windows)\n      test.sh           --> autotests unit tests with Testacular (*nix)\n      web-server.js     --> simple development webserver based on node.js\n\n    test/               --> test source files and libraries\n      e2e/              -->\n        runner.html     --> end-to-end test runner (open in your browser to run)\n        scenarios.js    --> end-to-end specs\n      lib/\n        angular/                --> angular testing libraries\n          angular-mocks.js      --> mocks that replace certain angular services in tests\n          angular-scenario.js   --> angular's scenario (end-to-end) test runner library\n          version.txt           --> version file\n      unit/                     --> unit level specs/tests\n        controllersSpec.js      --> specs for controllers\n        directivessSpec.js      --> specs for directives\n        filtersSpec.js          --> specs for filters\n        servicesSpec.js         --> specs for services\n\n## Contact\n\nFor more information on AngularJS please check out http://angularjs.org/\n"
  },
  {
    "path": "chapter4/recipe4/app/css/.gitignore",
    "content": ""
  },
  {
    "path": "chapter4/recipe4/app/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter4/recipe4/app/img/.gitignore",
    "content": ""
  },
  {
    "path": "chapter4/recipe4/app/index-async.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <style>\n    [ng-cloak] {\n      display: none;\n    }\n  </style>\n  <script>\n    // include angular loader, which allows the files to load in any order\n    /*\n     AngularJS v1.0.0rc1\n     (c) 2010-2012 AngularJS http://angularjs.org\n     License: MIT\n    */\n    'use strict';(function(i){function d(c,a,e){return c[a]||(c[a]=e())}return d(d(i,\"angular\",Object),\"module\",function(){var c={};return function(a,e,f){e&&c.hasOwnProperty(a)&&(c[a]=null);return d(c,a,function(){function b(a,b,d){return function(){c[d||\"push\"]([a,b,arguments]);return g}}if(!e)throw Error(\"No module: \"+a);var c=[],d=[],h=b(\"$injector\",\"invoke\"),g={_invokeQueue:c,_runBlocks:d,requires:e,name:a,provider:b(\"$provide\",\"provider\"),factory:b(\"$provide\",\"factory\"),service:b(\"$provide\",\"service\"),\n    value:b(\"$provide\",\"value\"),constant:b(\"$provide\",\"constant\",\"unshift\"),filter:b(\"$filterProvider\",\"register\"),directive:b(\"$compileProvider\",\"directive\"),config:h,run:function(a){d.push(a);return this}};f&&h(f);return g})}})})(window);\n\n    // include a third-party async loader library\n    /*!\n     * $script.js v1.3\n     * https://github.com/ded/script.js\n     * Copyright: @ded & @fat - Dustin Diaz, Jacob Thornton 2011\n     * Follow our software http://twitter.com/dedfat\n     * License: MIT\n     */\n    !function(a,b,c){function t(a,c){var e=b.createElement(\"script\"),f=j;e.onload=e.onerror=e[o]=function(){e[m]&&!/^c|loade/.test(e[m])||f||(e.onload=e[o]=null,f=1,c())},e.async=1,e.src=a,d.insertBefore(e,d.firstChild)}function q(a,b){p(a,function(a){return!b(a)})}var d=b.getElementsByTagName(\"head\")[0],e={},f={},g={},h={},i=\"string\",j=!1,k=\"push\",l=\"DOMContentLoaded\",m=\"readyState\",n=\"addEventListener\",o=\"onreadystatechange\",p=function(a,b){for(var c=0,d=a.length;c<d;++c)if(!b(a[c]))return j;return 1};!b[m]&&b[n]&&(b[n](l,function r(){b.removeEventListener(l,r,j),b[m]=\"complete\"},j),b[m]=\"loading\");var s=function(a,b,d){function o(){if(!--m){e[l]=1,j&&j();for(var a in g)p(a.split(\"|\"),n)&&!q(g[a],n)&&(g[a]=[])}}function n(a){return a.call?a():e[a]}a=a[k]?a:[a];var i=b&&b.call,j=i?b:d,l=i?a.join(\"\"):b,m=a.length;c(function(){q(a,function(a){h[a]?(l&&(f[l]=1),o()):(h[a]=1,l&&(f[l]=1),t(s.path?s.path+a+\".js\":a,o))})},0);return s};s.get=t,s.ready=function(a,b,c){a=a[k]?a:[a];var d=[];!q(a,function(a){e[a]||d[k](a)})&&p(a,function(a){return e[a]})?b():!function(a){g[a]=g[a]||[],g[a][k](b),c&&c(d)}(a.join(\"|\"));return s};var u=a.$script;s.noConflict=function(){a.$script=u;return this},typeof module!=\"undefined\"&&module.exports?module.exports=s:a.$script=s}(this,document,setTimeout)\n\n    // load all of the dependencies asynchronously.\n    $script([\n      'lib/angular/angular.js',\n      'js/app.js',\n      'js/services.js',\n      'js/controllers.js',\n      'js/filters.js',\n      'js/directives.js'\n    ], function() {\n      // when all is done, execute bootstrap angular application\n      angular.bootstrap(document, ['myApp']);\n    });\n  </script>\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\">\n</head>\n<body ng-cloak>\n  <ul class=\"menu\">\n    <li><a href=\"#/view1\">view1</a></li>\n    <li><a href=\"#/view2\">view2</a></li>\n  </ul>\n\n  <div ng-view></div>\n\n  <div>Angular seed app: v<span app-version></span></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "chapter4/recipe4/app/index.html",
    "content": "<!doctype html>\n<html lang=\"en\" ng-app=\"MyApp\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/bootstrap.css\"/>\n</head>\n<body ng-init=\"data = true\">\n  <p>{{ data | checkmark}}</p>\n  <p>{{ !data | checkmark}}</p>\n  <script src=\"lib/angular/angular.js\"></script>\n  <script src=\"js/app.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "chapter4/recipe4/app/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.filter('checkmark', function() {\n  return function(input) {\n    return input ? '\\u2713' : '\\u2718';\n  };\n});"
  },
  {
    "path": "chapter4/recipe4/app/lib/angular/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngCookies\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookies\n   * @requires $browser\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from\n   * this object, new cookies are created/deleted at the end of current $eval.\n   *\n   * @example\n   */\n   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for(name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            if (angular.isDefined(lastCookies[name])) {\n              cookies[name] = lastCookies[name];\n            } else {\n              delete cookies[name];\n            }\n          } else if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated){\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   * @example\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#get\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          return angular.fromJson($cookies[key]);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#put\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#remove\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter4/recipe4/app/lib/angular/angular-loader.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n\n(\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n'use strict';\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n)(window);\n\n/**\n * Closure compiler type information\n *\n * @typedef { {\n *   requires: !Array.<string>,\n *   invokeQueue: !Array.<Array.<*>>,\n *\n *   service: function(string, Function):angular.Module,\n *   factory: function(string, Function):angular.Module,\n *   value: function(string, *):angular.Module,\n *\n *   filter: function(string, Function):angular.Module,\n *\n *   init: function(Function):angular.Module\n * } }\n */\nangular.Module;\n\n"
  },
  {
    "path": "chapter4/recipe4/app/lib/angular/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g. \n *   `http://example.com:8080/api`), you'll need to escape the colon character before the port\n *   number, like this: `$resource('http://example.com\\\\:8080/api')`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` – {string} – The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` – {object=} – Optional set of pre-bound parameters for this action.\n *   - isArray – {boolean=} – If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n     * encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace((pctEncodeSpaces ? null : /%20/g), '+');\n    }\n\n    function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        action.method = angular.uppercase(action.method);\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter4/recipe4/app/lib/angular/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             '<p style=\"color:blue\">an html\\n' +\n             '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n             'snippet</p>';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n          Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n           <table>\n             <tr>\n               <td>Filter</td>\n               <td>Source</td>\n               <td>Rendered</td>\n             </tr>\n             <tr id=\"html-filter\">\n               <td>html filter</td>\n               <td>\n                 <pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre>\n               </td>\n               <td>\n                 <div ng-bind-html=\"snippet\"></div>\n               </td>\n             </tr>\n             <tr id=\"escaped-html\">\n               <td>no filter</td>\n               <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind=\"snippet\"></div></td>\n             </tr>\n             <tr id=\"html-unsafe-filter\">\n               <td>unsafe html filter</td>\n               <td><pre>&lt;div ng-bind-html-unsafe=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind-html-unsafe=\"snippet\"></div></td>\n             </tr>\n           </table>\n         </div>\n     </doc:source>\n     <doc:scenario>\n       it('should sanitize the html snippet ', function() {\n         expect(using('#html-filter').element('div').html()).\n           toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n       });\n\n       it('should escape snippet without any filter', function() {\n         expect(using('#escaped-html').element('div').html()).\n           toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n                \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n                \"snippet&lt;/p&gt;\");\n       });\n\n       it('should inline raw snippet if filtered as unsafe', function() {\n         expect(using('#html-unsafe-filter').element(\"div\").html()).\n           toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n                \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n                \"snippet</p>\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new <b>text</b>');\n         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');\n         expect(using('#escaped-html').element('div').html()).toBe(\"new &lt;b&gt;text&lt;/b&gt;\");\n         expect(using('#html-unsafe-filter').binding(\"snippet\")).toBe('new <b>text</b>');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar $sanitize = function(html) {\n  var buf = [];\n    htmlParser(html, htmlSanitizeWriter(buf));\n    return buf.join('');\n};\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP = /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  URI_REGEXP = /^((ftp|https?):\\/\\/|mailto:|#)/,\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g; // Match everything outside of normal chars and \" (quote character)\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,aside,\" +\n        \"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,\" +\n        \"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,bdi,bdo,\" +\n        \"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,\" +\n        \"span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        index = html.indexOf(\"-->\");\n\n        if ( index >= 0 ) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'), function(all, text){\n        text = text.\n          replace(COMMENT_REGEXP, \"$1\").\n          replace(CDATA_REGEXP, \"$1\");\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n\n        return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw \"Parse Error: \" + html;\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {\n      var value = doubleQuotedValue\n        || singleQoutedValue\n        || unqoutedValue\n        || '';\n\n      attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nvar hiddenPre=document.createElement(\"pre\");\nfunction decodeEntities(value) {\n  hiddenPre.innerHTML=value.replace(/</g,\"&lt;\");\n  return hiddenPre.innerText || hiddenPre.textContent || '';\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] == true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] == true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).value('$sanitize', $sanitize);\n\n/**\n * @ngdoc directive\n * @name ngSanitize.directive:ngBindHtml\n *\n * @description\n * Creates a binding that will sanitize the result of evaluating the `expression` with the\n * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n */\nangular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);\n    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {\n      value = $sanitize(value);\n      element.html(value || '');\n    });\n  };\n}]);\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n *   plain email address links.\n *\n * @param {string} text Input text.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should linkify the snippet with urls', function() {\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('Pretty text with some links:&#10;' +\n                '<a href=\"http://angularjs.org/\">http://angularjs.org/</a>,&#10;' +\n                '<a href=\"mailto:us@somewhere.org\">us@somewhere.org</a>,&#10;' +\n                '<a href=\"mailto:another@somewhere.org\">another@somewhere.org</a>,&#10;' +\n                'and one more: <a href=\"ftp://127.0.0.1/\">ftp://127.0.0.1/</a>.');\n       });\n\n       it ('should not linkify snippet without the linky filter', function() {\n         expect(using('#escaped-html').binding('snippet')).\n           toBe(\"Pretty text with some links:\\n\" +\n                \"http://angularjs.org/,\\n\" +\n                \"mailto:us@somewhere.org,\\n\" +\n                \"another@somewhere.org,\\n\" +\n                \"and one more: ftp://127.0.0.1/.\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new http://link.');\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('new <a href=\"http://link\">http://link</a>.');\n         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', function() {\n  var LINKY_URL_REGEXP = /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s\\.\\;\\,\\(\\)\\{\\}\\<\\>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    // TODO(vojta): use $sanitize instead\n    var writer = htmlSanitizeWriter(html);\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      writer.chars(raw.substr(0, i));\n      writer.start('a', {href:url});\n      writer.chars(match[0].replace(MAILTO_REGEXP, ''));\n      writer.end('a');\n      raw = raw.substring(i + match[0].length);\n    }\n    writer.chars(raw);\n    return html.join('');\n  };\n});\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter4/recipe4/app/lib/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter4/recipe4/app/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter4/recipe4/app/partials/.gitignore",
    "content": ""
  },
  {
    "path": "chapter4/recipe4/app/partials/partial1.html",
    "content": "<p>This is the partial for view 1.</p>\n"
  },
  {
    "path": "chapter4/recipe4/app/partials/partial2.html",
    "content": "<p>This is the partial for view 2.</p>\n<p>\n  Showing of 'interpolate' filter:\n  {{ 'Current version is v%VERSION%.' | interpolate }}\n</p>\n"
  },
  {
    "path": "chapter4/recipe4/config/testacular-e2e.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  ANGULAR_SCENARIO,\n  ANGULAR_SCENARIO_ADAPTER,\n  'test/e2e/**/*.js'\n];\n\nautoWatch = false;\n\nbrowsers = ['Chrome'];\n\nsingleRun = true;\n\nproxies = {\n  '/': 'http://localhost:8000/'\n};\n\njunitReporter = {\n  outputFile: 'test_out/e2e.xml',\n  suite: 'e2e'\n};\n"
  },
  {
    "path": "chapter4/recipe4/config/testacular.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  JASMINE,\n  JASMINE_ADAPTER,\n  'app/lib/jquery.min.js',\n  'app/lib/angular/angular.js',\n  'app/lib/angular/angular-*.js',\n  'test/lib/angular/angular-mocks.js',\n  'test/lib/jasmine-jquery.js',\n  'app/js/**/*.js',\n  'test/unit/**/*.js'\n];\n\nautoWatch = true;\n\nbrowsers = ['Chrome'];\n\njunitReporter = {\n  outputFile: 'test_out/unit.xml',\n  suite: 'unit'\n};\n"
  },
  {
    "path": "chapter4/recipe4/logs/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "chapter4/recipe4/scripts/e2e-test.bat",
    "content": "@echo off\n\nREM Windows script for running e2e tests\nREM You have to run server and capture some browser first\nREM\nREM Requirements:\nREM - NodeJS (http://nodejs.org/)\nREM - Testacular (npm install -g testacular)\n\nset BASE_DIR=%~dp0\ntestacular start \"%BASE_DIR%\\..\\config\\testacular-e2e.conf.js\" %*\n"
  },
  {
    "path": "chapter4/recipe4/scripts/e2e-test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular-e2e.conf.js $*\n"
  },
  {
    "path": "chapter4/recipe4/scripts/test.bat",
    "content": "@echo off\r\n\r\nREM Windows script for running unit tests\r\nREM You have to run server and capture some browser first\r\nREM\r\nREM Requirements:\r\nREM - NodeJS (http://nodejs.org/)\r\nREM - Testacular (npm install -g testacular)\r\n\r\nset BASE_DIR=%~dp0\r\ntestacular start \"%BASE_DIR%\\..\\config\\testacular.conf.js\" %*\r\n"
  },
  {
    "path": "chapter4/recipe4/scripts/test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular.conf.js $*\n"
  },
  {
    "path": "chapter4/recipe4/scripts/watchr.rb",
    "content": "#!/usr/bin/env watchr\n\n# config file for watchr http://github.com/mynyml/watchr\n# install: gem install watchr\n# run: watch watchr.rb\n# note: make sure that you have jstd server running (server.sh) and a browser captured\n\nlog_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log')\n\n`cd ..`\n`touch #{log_file}`\n\nputs \"String watchr... log file: #{log_file}\"\n\nwatch( '(app/js|test/unit)' )  do\n  `echo \"\\n\\ntest run started @ \\`date\\`\" > #{log_file}`\n  `scripts/test.sh &> #{log_file}`\nend\n\n"
  },
  {
    "path": "chapter4/recipe4/scripts/web-server.js",
    "content": "#!/usr/bin/env node\n\nvar util = require('util'),\n    http = require('http'),\n    fs = require('fs'),\n    url = require('url'),\n    events = require('events');\n\nvar DEFAULT_PORT = 8000;\n\nfunction main(argv) {\n  new HttpServer({\n    'GET': createServlet(StaticServlet),\n    'HEAD': createServlet(StaticServlet)\n  }).start(Number(argv[2]) || DEFAULT_PORT);\n}\n\nfunction escapeHtml(value) {\n  return value.toString().\n    replace('<', '&lt;').\n    replace('>', '&gt;').\n    replace('\"', '&quot;');\n}\n\nfunction createServlet(Class) {\n  var servlet = new Class();\n  return servlet.handleRequest.bind(servlet);\n}\n\n/**\n * An Http server implementation that uses a map of methods to decide\n * action routing.\n *\n * @param {Object} Map of method => Handler function\n */\nfunction HttpServer(handlers) {\n  this.handlers = handlers;\n  this.server = http.createServer(this.handleRequest_.bind(this));\n}\n\nHttpServer.prototype.start = function(port) {\n  this.port = port;\n  this.server.listen(port);\n  util.puts('Http Server running at http://localhost:' + port + '/');\n};\n\nHttpServer.prototype.parseUrl_ = function(urlString) {\n  var parsed = url.parse(urlString);\n  parsed.pathname = url.resolve('/', parsed.pathname);\n  return url.parse(url.format(parsed), true);\n};\n\nHttpServer.prototype.handleRequest_ = function(req, res) {\n  var logEntry = req.method + ' ' + req.url;\n  if (req.headers['user-agent']) {\n    logEntry += ' ' + req.headers['user-agent'];\n  }\n  util.puts(logEntry);\n  req.url = this.parseUrl_(req.url);\n  var handler = this.handlers[req.method];\n  if (!handler) {\n    res.writeHead(501);\n    res.end();\n  } else {\n    handler.call(this, req, res);\n  }\n};\n\n/**\n * Handles static content.\n */\nfunction StaticServlet() {}\n\nStaticServlet.MimeMap = {\n  'txt': 'text/plain',\n  'html': 'text/html',\n  'css': 'text/css',\n  'xml': 'application/xml',\n  'json': 'application/json',\n  'js': 'application/javascript',\n  'jpg': 'image/jpeg',\n  'jpeg': 'image/jpeg',\n  'gif': 'image/gif',\n  'png': 'image/png',\n  'svg': 'image/svg+xml'\n};\n\nStaticServlet.prototype.handleRequest = function(req, res) {\n  var self = this;\n  var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){\n    return String.fromCharCode(parseInt(hex, 16));\n  });\n  var parts = path.split('/');\n  if (parts[parts.length-1].charAt(0) === '.')\n    return self.sendForbidden_(req, res, path);\n  fs.stat(path, function(err, stat) {\n    if (err)\n      return self.sendMissing_(req, res, path);\n    if (stat.isDirectory())\n      return self.sendDirectory_(req, res, path);\n    return self.sendFile_(req, res, path);\n  });\n}\n\nStaticServlet.prototype.sendError_ = function(req, res, error) {\n  res.writeHead(500, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>Internal Server Error</title>\\n');\n  res.write('<h1>Internal Server Error</h1>');\n  res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');\n  util.puts('500 Internal Server Error');\n  util.puts(util.inspect(error));\n};\n\nStaticServlet.prototype.sendMissing_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(404, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>404 Not Found</title>\\n');\n  res.write('<h1>Not Found</h1>');\n  res.write(\n    '<p>The requested URL ' +\n    escapeHtml(path) +\n    ' was not found on this server.</p>'\n  );\n  res.end();\n  util.puts('404 Not Found: ' + path);\n};\n\nStaticServlet.prototype.sendForbidden_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(403, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>403 Forbidden</title>\\n');\n  res.write('<h1>Forbidden</h1>');\n  res.write(\n    '<p>You do not have permission to access ' +\n    escapeHtml(path) + ' on this server.</p>'\n  );\n  res.end();\n  util.puts('403 Forbidden: ' + path);\n};\n\nStaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {\n  res.writeHead(301, {\n      'Content-Type': 'text/html',\n      'Location': redirectUrl\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>301 Moved Permanently</title>\\n');\n  res.write('<h1>Moved Permanently</h1>');\n  res.write(\n    '<p>The document has moved <a href=\"' +\n    redirectUrl +\n    '\">here</a>.</p>'\n  );\n  res.end();\n  util.puts('301 Moved Permanently: ' + redirectUrl);\n};\n\nStaticServlet.prototype.sendFile_ = function(req, res, path) {\n  var self = this;\n  var file = fs.createReadStream(path);\n  res.writeHead(200, {\n    'Content-Type': StaticServlet.\n      MimeMap[path.split('.').pop()] || 'text/plain'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n  } else {\n    file.on('data', res.write.bind(res));\n    file.on('close', function() {\n      res.end();\n    });\n    file.on('error', function(error) {\n      self.sendError_(req, res, error);\n    });\n  }\n};\n\nStaticServlet.prototype.sendDirectory_ = function(req, res, path) {\n  var self = this;\n  if (path.match(/[^\\/]$/)) {\n    req.url.pathname += '/';\n    var redirectUrl = url.format(url.parse(url.format(req.url)));\n    return self.sendRedirect_(req, res, redirectUrl);\n  }\n  fs.readdir(path, function(err, files) {\n    if (err)\n      return self.sendError_(req, res, error);\n\n    if (!files.length)\n      return self.writeDirectoryIndex_(req, res, path, []);\n\n    var remaining = files.length;\n    files.forEach(function(fileName, index) {\n      fs.stat(path + '/' + fileName, function(err, stat) {\n        if (err)\n          return self.sendError_(req, res, err);\n        if (stat.isDirectory()) {\n          files[index] = fileName + '/';\n        }\n        if (!(--remaining))\n          return self.writeDirectoryIndex_(req, res, path, files);\n      });\n    });\n  });\n};\n\nStaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {\n  path = path.substring(1);\n  res.writeHead(200, {\n    'Content-Type': 'text/html'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n    return;\n  }\n  res.write('<!doctype html>\\n');\n  res.write('<title>' + escapeHtml(path) + '</title>\\n');\n  res.write('<style>\\n');\n  res.write('  ol { list-style-type: none; font-size: 1.2em; }\\n');\n  res.write('</style>\\n');\n  res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');\n  res.write('<ol>');\n  files.forEach(function(fileName) {\n    if (fileName.charAt(0) !== '.') {\n      res.write('<li><a href=\"' +\n        escapeHtml(fileName) + '\">' +\n        escapeHtml(fileName) + '</a></li>');\n    }\n  });\n  res.write('</ol>');\n  res.end();\n};\n\n// Must be last,\nmain(process.argv);\n"
  },
  {
    "path": "chapter4/recipe4/test/e2e/runner.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <title>End2end Test Runner</title>\n    <script src=\"../lib/angular/angular-scenario.js\" ng-autotest></script>\n    <script src=\"scenarios.js\"></script>\n  </head>\n  <body>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter4/recipe4/test/e2e/scenarios.js",
    "content": "'use strict';\n\n/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */\n\ndescribe('my app', function() {\n\n  beforeEach(function() {\n    browser().navigateTo('../../app/index.html');\n  });\n\n\n  it('should automatically redirect to /view1 when location hash/fragment is empty', function() {\n    expect(browser().location().url()).toBe(\"/view1\");\n  });\n\n\n  describe('view1', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view1');\n    });\n\n\n    it('should render view1 when user navigates to /view1', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 1/);\n    });\n\n  });\n\n\n  describe('view2', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view2');\n    });\n\n\n    it('should render view2 when user navigates to /view2', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 2/);\n    });\n\n  });\n});\n"
  },
  {
    "path": "chapter4/recipe4/test/lib/angular/angular-mocks.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n *\n * TODO(vojta): wrap whole file into closure during build\n */\n\n/**\n * @ngdoc overview\n * @name angular.mock\n * @description\n *\n * Namespace from 'angular-mocks.js' which contains testing related code.\n */\nangular.mock = {};\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ngMock.$browser\n *\n * @description\n * This service is a mock implementation of {@link ng.$browser}. It provides fake\n * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,\n * cookies, etc...\n *\n * The api of this service is the same as that of the real {@link ng.$browser $browser}, except\n * that there are several helper methods available which can be used in tests.\n */\nangular.mock.$BrowserProvider = function() {\n  this.$get = function(){\n    return new angular.mock.$Browser();\n  };\n};\n\nangular.mock.$Browser = function() {\n  var self = this;\n\n  this.isMock = true;\n  self.$$url = \"http://server/\";\n  self.$$lastUrl = self.$$url; // used by url polling fn\n  self.pollFns = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = angular.noop;\n  self.$$incOutstandingRequestCount = angular.noop;\n\n\n  // register url polling fn\n\n  self.onUrlChange = function(listener) {\n    self.pollFns.push(\n      function() {\n        if (self.$$lastUrl != self.$$url) {\n          self.$$lastUrl = self.$$url;\n          listener(self.$$url);\n        }\n      }\n    );\n\n    return listener;\n  };\n\n  self.cookieHash = {};\n  self.lastCookieHash = {};\n  self.deferredFns = [];\n  self.deferredNextId = 0;\n\n  self.defer = function(fn, delay) {\n    delay = delay || 0;\n    self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});\n    self.deferredFns.sort(function(a,b){ return a.time - b.time;});\n    return self.deferredNextId++;\n  };\n\n\n  self.defer.now = 0;\n\n\n  self.defer.cancel = function(deferId) {\n    var fnIndex;\n\n    angular.forEach(self.deferredFns, function(fn, index) {\n      if (fn.id === deferId) fnIndex = index;\n    });\n\n    if (fnIndex !== undefined) {\n      self.deferredFns.splice(fnIndex, 1);\n      return true;\n    }\n\n    return false;\n  };\n\n\n  /**\n   * @name ngMock.$browser#defer.flush\n   * @methodOf ngMock.$browser\n   *\n   * @description\n   * Flushes all pending requests and executes the defer callbacks.\n   *\n   * @param {number=} number of milliseconds to flush. See {@link #defer.now}\n   */\n  self.defer.flush = function(delay) {\n    if (angular.isDefined(delay)) {\n      self.defer.now += delay;\n    } else {\n      if (self.deferredFns.length) {\n        self.defer.now = self.deferredFns[self.deferredFns.length-1].time;\n      } else {\n        throw Error('No deferred tasks to be flushed');\n      }\n    }\n\n    while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {\n      self.deferredFns.shift().fn();\n    }\n  };\n  /**\n   * @name ngMock.$browser#defer.now\n   * @propertyOf ngMock.$browser\n   *\n   * @description\n   * Current milliseconds mock time.\n   */\n\n  self.$$baseHref = '';\n  self.baseHref = function() {\n    return this.$$baseHref;\n  };\n};\nangular.mock.$Browser.prototype = {\n\n/**\n  * @name ngMock.$browser#poll\n  * @methodOf ngMock.$browser\n  *\n  * @description\n  * run all fns in pollFns\n  */\n  poll: function poll() {\n    angular.forEach(this.pollFns, function(pollFn){\n      pollFn();\n    });\n  },\n\n  addPollFn: function(pollFn) {\n    this.pollFns.push(pollFn);\n    return pollFn;\n  },\n\n  url: function(url, replace) {\n    if (url) {\n      this.$$url = url;\n      return this;\n    }\n\n    return this.$$url;\n  },\n\n  cookies:  function(name, value) {\n    if (name) {\n      if (value == undefined) {\n        delete this.cookieHash[name];\n      } else {\n        if (angular.isString(value) &&       //strings only\n            value.length <= 4096) {          //strict cookie storage limits\n          this.cookieHash[name] = value;\n        }\n      }\n    } else {\n      if (!angular.equals(this.cookieHash, this.lastCookieHash)) {\n        this.lastCookieHash = angular.copy(this.cookieHash);\n        this.cookieHash = angular.copy(this.cookieHash);\n      }\n      return this.cookieHash;\n    }\n  },\n\n  notifyWhenNoOutstandingRequests: function(fn) {\n    fn();\n  }\n};\n\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandlerProvider\n *\n * @description\n * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed\n * into the `$exceptionHandler`.\n */\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandler\n *\n * @description\n * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed\n * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration\n * information.\n *\n *\n * <pre>\n *   describe('$exceptionHandlerProvider', function() {\n *\n *     it('should capture log messages and exceptions', function() {\n *\n *       module(function($exceptionHandlerProvider) {\n *         $exceptionHandlerProvider.mode('log');\n *       });\n *\n *       inject(function($log, $exceptionHandler, $timeout) {\n *         $timeout(function() { $log.log(1); });\n *         $timeout(function() { $log.log(2); throw 'banana peel'; });\n *         $timeout(function() { $log.log(3); });\n *         expect($exceptionHandler.errors).toEqual([]);\n *         expect($log.assertEmpty());\n *         $timeout.flush();\n *         expect($exceptionHandler.errors).toEqual(['banana peel']);\n *         expect($log.log.logs).toEqual([[1], [2], [3]]);\n *       });\n *     });\n *   });\n * </pre>\n */\n\nangular.mock.$ExceptionHandlerProvider = function() {\n  var handler;\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$exceptionHandlerProvider#mode\n   * @methodOf ngMock.$exceptionHandlerProvider\n   *\n   * @description\n   * Sets the logging mode.\n   *\n   * @param {string} mode Mode of operation, defaults to `rethrow`.\n   *\n   *   - `rethrow`: If any errors are are passed into the handler in tests, it typically\n   *                means that there is a bug in the application or test, so this mock will\n   *                make these tests fail.\n   *   - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores an\n   *            array of errors in `$exceptionHandler.errors`, to allow later assertion of them.\n   *            See {@link ngMock.$log#assertEmpty assertEmpty()} and\n   *             {@link ngMock.$log#reset reset()}\n   */\n  this.mode = function(mode) {\n    switch(mode) {\n      case 'rethrow':\n        handler = function(e) {\n          throw e;\n        };\n        break;\n      case 'log':\n        var errors = [];\n\n        handler = function(e) {\n          if (arguments.length == 1) {\n            errors.push(e);\n          } else {\n            errors.push([].slice.call(arguments, 0));\n          }\n        };\n\n        handler.errors = errors;\n        break;\n      default:\n        throw Error(\"Unknown mode '\" + mode + \"', only 'log'/'rethrow' modes are allowed!\");\n    }\n  };\n\n  this.$get = function() {\n    return handler;\n  };\n\n  this.mode('rethrow');\n};\n\n\n/**\n * @ngdoc service\n * @name ngMock.$log\n *\n * @description\n * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays\n * (one array per logging level). These arrays are exposed as `logs` property of each of the\n * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.\n *\n */\nangular.mock.$LogProvider = function() {\n\n  function concat(array1, array2, index) {\n    return array1.concat(Array.prototype.slice.call(array2, index));\n  }\n\n\n  this.$get = function () {\n    var $log = {\n      log: function() { $log.log.logs.push(concat([], arguments, 0)); },\n      warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },\n      info: function() { $log.info.logs.push(concat([], arguments, 0)); },\n      error: function() { $log.error.logs.push(concat([], arguments, 0)); }\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#reset\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Reset all of the logging arrays to empty.\n     */\n    $log.reset = function () {\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#log.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.log.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#warn.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.warn.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#info.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.info.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#error.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.error.logs = [];\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#assertEmpty\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.\n     */\n    $log.assertEmpty = function() {\n      var errors = [];\n      angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {\n        angular.forEach($log[logLevel].logs, function(log) {\n          angular.forEach(log, function (logItem) {\n            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\\n' + (logItem.stack || ''));\n          });\n        });\n      });\n      if (errors.length) {\n        errors.unshift(\"Expected $log to be empty! Either a message was logged unexpectedly, or an expected \" +\n          \"log message was not checked and removed:\");\n        errors.push('');\n        throw new Error(errors.join('\\n---------\\n'));\n      }\n    };\n\n    $log.reset();\n    return $log;\n  };\n};\n\n\n(function() {\n  var R_ISO8061_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?:\\:?(\\d\\d)(?:\\:?(\\d\\d)(?:\\.(\\d{3}))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d)))?$/;\n\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8061_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n  function int(str) {\n    return parseInt(str, 10);\n  }\n\n  function padNumber(num, digits, trim) {\n    var neg = '';\n    if (num < 0) {\n      neg =  '-';\n      num = -num;\n    }\n    num = '' + num;\n    while(num.length < digits) num = '0' + num;\n    if (trim)\n      num = num.substr(num.length - digits);\n    return neg + num;\n  }\n\n\n  /**\n   * @ngdoc object\n   * @name angular.mock.TzDate\n   * @description\n   *\n   * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.\n   *\n   * Mock of the Date type which has its timezone specified via constroctor arg.\n   *\n   * The main purpose is to create Date-like instances with timezone fixed to the specified timezone\n   * offset, so that we can test code that depends on local timezone settings without dependency on\n   * the time zone settings of the machine where the code is running.\n   *\n   * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)\n   * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*\n   *\n   * @example\n   * !!!! WARNING !!!!!\n   * This is not a complete Date object so only methods that were implemented can be called safely.\n   * To make matters worse, TzDate instances inherit stuff from Date via a prototype.\n   *\n   * We do our best to intercept calls to \"unimplemented\" methods, but since the list of methods is\n   * incomplete we might be missing some non-standard methods. This can result in errors like:\n   * \"Date.prototype.foo called on incompatible Object\".\n   *\n   * <pre>\n   * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');\n   * newYearInBratislava.getTimezoneOffset() => -60;\n   * newYearInBratislava.getFullYear() => 2010;\n   * newYearInBratislava.getMonth() => 0;\n   * newYearInBratislava.getDate() => 1;\n   * newYearInBratislava.getHours() => 0;\n   * newYearInBratislava.getMinutes() => 0;\n   * </pre>\n   *\n   */\n  angular.mock.TzDate = function (offset, timestamp) {\n    var self = new Date(0);\n    if (angular.isString(timestamp)) {\n      var tsStr = timestamp;\n\n      self.origDate = jsonStringToDate(timestamp);\n\n      timestamp = self.origDate.getTime();\n      if (isNaN(timestamp))\n        throw {\n          name: \"Illegal Argument\",\n          message: \"Arg '\" + tsStr + \"' passed into TzDate constructor is not a valid date string\"\n        };\n    } else {\n      self.origDate = new Date(timestamp);\n    }\n\n    var localOffset = new Date(timestamp).getTimezoneOffset();\n    self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;\n    self.date = new Date(timestamp + self.offsetDiff);\n\n    self.getTime = function() {\n      return self.date.getTime() - self.offsetDiff;\n    };\n\n    self.toLocaleDateString = function() {\n      return self.date.toLocaleDateString();\n    };\n\n    self.getFullYear = function() {\n      return self.date.getFullYear();\n    };\n\n    self.getMonth = function() {\n      return self.date.getMonth();\n    };\n\n    self.getDate = function() {\n      return self.date.getDate();\n    };\n\n    self.getHours = function() {\n      return self.date.getHours();\n    };\n\n    self.getMinutes = function() {\n      return self.date.getMinutes();\n    };\n\n    self.getSeconds = function() {\n      return self.date.getSeconds();\n    };\n\n    self.getTimezoneOffset = function() {\n      return offset * 60;\n    };\n\n    self.getUTCFullYear = function() {\n      return self.origDate.getUTCFullYear();\n    };\n\n    self.getUTCMonth = function() {\n      return self.origDate.getUTCMonth();\n    };\n\n    self.getUTCDate = function() {\n      return self.origDate.getUTCDate();\n    };\n\n    self.getUTCHours = function() {\n      return self.origDate.getUTCHours();\n    };\n\n    self.getUTCMinutes = function() {\n      return self.origDate.getUTCMinutes();\n    };\n\n    self.getUTCSeconds = function() {\n      return self.origDate.getUTCSeconds();\n    };\n\n    self.getUTCMilliseconds = function() {\n      return self.origDate.getUTCMilliseconds();\n    };\n\n    self.getDay = function() {\n      return self.date.getDay();\n    };\n\n    // provide this method only on browsers that already have it\n    if (self.toISOString) {\n      self.toISOString = function() {\n        return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +\n              padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +\n              padNumber(self.origDate.getUTCDate(), 2) + 'T' +\n              padNumber(self.origDate.getUTCHours(), 2) + ':' +\n              padNumber(self.origDate.getUTCMinutes(), 2) + ':' +\n              padNumber(self.origDate.getUTCSeconds(), 2) + '.' +\n              padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'\n      }\n    }\n\n    //hide all methods not implemented in this mock that the Date prototype exposes\n    var unimplementedMethods = ['getMilliseconds', 'getUTCDay',\n        'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',\n        'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',\n        'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',\n        'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',\n        'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];\n\n    angular.forEach(unimplementedMethods, function(methodName) {\n      self[methodName] = function() {\n        throw Error(\"Method '\" + methodName + \"' is not implemented in the TzDate mock\");\n      };\n    });\n\n    return self;\n  };\n\n  //make \"tzDateInstance instanceof Date\" return true\n  angular.mock.TzDate.prototype = Date.prototype;\n})();\n\n\n/**\n * @ngdoc function\n * @name angular.mock.dump\n * @description\n *\n * *NOTE*: this is not an injectable instance, just a globally available function.\n *\n * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.\n *\n * This method is also available on window, where it can be used to display objects on debug console.\n *\n * @param {*} object - any object to turn into string.\n * @return {string} a serialized string of the argument\n */\nangular.mock.dump = function(object) {\n  return serialize(object);\n\n  function serialize(object) {\n    var out;\n\n    if (angular.isElement(object)) {\n      object = angular.element(object);\n      out = angular.element('<div></div>');\n      angular.forEach(object, function(element) {\n        out.append(angular.element(element).clone());\n      });\n      out = out.html();\n    } else if (angular.isArray(object)) {\n      out = [];\n      angular.forEach(object, function(o) {\n        out.push(serialize(o));\n      });\n      out = '[ ' + out.join(', ') + ' ]';\n    } else if (angular.isObject(object)) {\n      if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {\n        out = serializeScope(object);\n      } else if (object instanceof Error) {\n        out = object.stack || ('' + object.name + ': ' + object.message);\n      } else {\n        out = angular.toJson(object, true);\n      }\n    } else {\n      out = String(object);\n    }\n\n    return out;\n  }\n\n  function serializeScope(scope, offset) {\n    offset = offset ||  '  ';\n    var log = [offset + 'Scope(' + scope.$id + '): {'];\n    for ( var key in scope ) {\n      if (scope.hasOwnProperty(key) && !key.match(/^(\\$|this)/)) {\n        log.push('  ' + key + ': ' + angular.toJson(scope[key]));\n      }\n    }\n    var child = scope.$$childHead;\n    while(child) {\n      log.push(serializeScope(child, offset + '  '));\n      child = child.$$nextSibling;\n    }\n    log.push('}');\n    return log.join('\\n' + offset);\n  }\n};\n\n/**\n * @ngdoc object\n * @name ngMock.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for unit testing application that use the\n * {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less\n * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.\n *\n * During unit testing, we want our unit tests to run quickly and have no external dependencies so\n * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or\n * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is\n * to verify whether a certain request has been sent or not, or alternatively just let the\n * application make requests, respond with pre-trained responses and assert that the end result is\n * what we expect it to be.\n *\n * This mock implementation can be used to respond with static or dynamic responses via the\n * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).\n *\n * When an Angular application needs some data from a server, it calls the $http service, which\n * sends the request to a real server using $httpBackend service. With dependency injection, it is\n * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify\n * the requests and respond with some testing data without sending a request to real server.\n *\n * There are two ways to specify what test data should be returned as http responses by the mock\n * backend when the code under test makes http requests:\n *\n * - `$httpBackend.expect` - specifies a request expectation\n * - `$httpBackend.when` - specifies a backend definition\n *\n *\n * # Request Expectations vs Backend Definitions\n *\n * Request expectations provide a way to make assertions about requests made by the application and\n * to define responses for those requests. The test will fail if the expected requests are not made\n * or they are made in the wrong order.\n *\n * Backend definitions allow you to define a fake backend for your application which doesn't assert\n * if a particular request was made or not, it just returns a trained response if a request is made.\n * The test will pass whether or not the request gets made during testing.\n *\n *\n * <table class=\"table\">\n *   <tr><th width=\"220px\"></th><th>Request expectations</th><th>Backend definitions</th></tr>\n *   <tr>\n *     <th>Syntax</th>\n *     <td>.expect(...).respond(...)</td>\n *     <td>.when(...).respond(...)</td>\n *   </tr>\n *   <tr>\n *     <th>Typical usage</th>\n *     <td>strict unit tests</td>\n *     <td>loose (black-box) unit testing</td>\n *   </tr>\n *   <tr>\n *     <th>Fulfills multiple requests</th>\n *     <td>NO</td>\n *     <td>YES</td>\n *   </tr>\n *   <tr>\n *     <th>Order of requests matters</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Request required</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Response required</th>\n *     <td>optional (see below)</td>\n *     <td>YES</td>\n *   </tr>\n * </table>\n *\n * In cases where both backend definitions and request expectations are specified during unit\n * testing, the request expectations are evaluated first.\n *\n * If a request expectation has no response specified, the algorithm will search your backend\n * definitions for an appropriate response.\n *\n * If a request didn't match any expectation or if the expectation doesn't have the response\n * defined, the backend definitions are evaluated in sequential order to see if any of them match\n * the request. The response from the first matched definition is returned.\n *\n *\n * # Flushing HTTP requests\n *\n * The $httpBackend used in production, always responds to requests with responses asynchronously.\n * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are\n * hard to write, follow and maintain. At the same time the testing mock, can't respond\n * synchronously because that would change the execution of the code under test. For this reason the\n * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending\n * requests and thus preserving the async api of the backend, while allowing the test to execute\n * synchronously.\n *\n *\n * # Unit testing with mock $httpBackend\n *\n * <pre>\n   // controller\n   function MyController($scope, $http) {\n     $http.get('/auth.py').success(function(data) {\n       $scope.user = data;\n     });\n\n     this.saveMessage = function(message) {\n       $scope.status = 'Saving...';\n       $http.post('/add-msg.py', message).success(function(response) {\n         $scope.status = '';\n       }).error(function() {\n         $scope.status = 'ERROR!';\n       });\n     };\n   }\n\n   // testing controller\n   var $httpBackend;\n\n   beforeEach(inject(function($injector) {\n     $httpBackend = $injector.get('$httpBackend');\n\n     // backend definition common for all tests\n     $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});\n   }));\n\n\n   afterEach(function() {\n     $httpBackend.verifyNoOutstandingExpectation();\n     $httpBackend.verifyNoOutstandingRequest();\n   });\n\n\n   it('should fetch authentication token', function() {\n     $httpBackend.expectGET('/auth.py');\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n   });\n\n\n   it('should send msg to server', function() {\n     // now you don’t care about the authentication, but\n     // the controller will still send the request and\n     // $httpBackend will respond without you having to\n     // specify the expectation and response for this request\n     $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');\n\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n     controller.saveMessage('message content');\n     expect(controller.status).toBe('Saving...');\n     $httpBackend.flush();\n     expect(controller.status).toBe('');\n   });\n\n\n   it('should send auth header', function() {\n     $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {\n       // check if the header was send, if it wasn't the expectation won't\n       // match the request and the test will fail\n       return headers['Authorization'] == 'xxx';\n     }).respond(201, '');\n\n     var controller = scope.$new(MyController);\n     controller.saveMessage('whatever');\n     $httpBackend.flush();\n   });\n   </pre>\n */\nangular.mock.$HttpBackendProvider = function() {\n  this.$get = [createHttpBackendMock];\n};\n\n/**\n * General factory function for $httpBackend mock.\n * Returns instance for unit testing (when no arguments specified):\n *   - passing through is disabled\n *   - auto flushing is disabled\n *\n * Returns instance for e2e testing (when `$delegate` and `$browser` specified):\n *   - passing through (delegating request to real backend) is enabled\n *   - auto flushing is enabled\n *\n * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)\n * @param {Object=} $browser Auto-flushing enabled if specified\n * @return {Object} Instance of $httpBackend mock\n */\nfunction createHttpBackendMock($delegate, $browser) {\n  var definitions = [],\n      expectations = [],\n      responses = [],\n      responsesPush = angular.bind(responses, responses.push);\n\n  function createResponse(status, data, headers) {\n    if (angular.isFunction(status)) return status;\n\n    return function() {\n      return angular.isNumber(status)\n          ? [status, data, headers]\n          : [200, status, data];\n    };\n  }\n\n  // TODO(vojta): change params to: method, url, data, headers, callback\n  function $httpBackend(method, url, data, callback, headers) {\n    var xhr = new MockXhr(),\n        expectation = expectations[0],\n        wasExpected = false;\n\n    function prettyPrint(data) {\n      return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)\n          ? data\n          : angular.toJson(data);\n    }\n\n    if (expectation && expectation.match(method, url)) {\n      if (!expectation.matchData(data))\n        throw Error('Expected ' + expectation + ' with different data\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.data) + '\\nGOT:      ' + data);\n\n      if (!expectation.matchHeaders(headers))\n        throw Error('Expected ' + expectation + ' with different headers\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.headers) + '\\nGOT:      ' +\n            prettyPrint(headers));\n\n      expectations.shift();\n\n      if (expectation.response) {\n        responses.push(function() {\n          var response = expectation.response(method, url, data, headers);\n          xhr.$$respHeaders = response[2];\n          callback(response[0], response[1], xhr.getAllResponseHeaders());\n        });\n        return;\n      }\n      wasExpected = true;\n    }\n\n    var i = -1, definition;\n    while ((definition = definitions[++i])) {\n      if (definition.match(method, url, data, headers || {})) {\n        if (definition.response) {\n          // if $browser specified, we do auto flush all requests\n          ($browser ? $browser.defer : responsesPush)(function() {\n            var response = definition.response(method, url, data, headers);\n            xhr.$$respHeaders = response[2];\n            callback(response[0], response[1], xhr.getAllResponseHeaders());\n          });\n        } else if (definition.passThrough) {\n          $delegate(method, url, data, callback, headers);\n        } else throw Error('No response defined !');\n        return;\n      }\n    }\n    throw wasExpected ?\n        Error('No response defined !') :\n        Error('Unexpected request: ' + method + ' ' + url + '\\n' +\n              (expectation ? 'Expected ' + expectation : 'No more request expected'));\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#when\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current definition.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.when = function(method, url, data, headers) {\n    var definition = new MockHttpExpectation(method, url, data, headers),\n        chain = {\n          respond: function(status, data, headers) {\n            definition.response = createResponse(status, data, headers);\n          }\n        };\n\n    if ($browser) {\n      chain.passThrough = function() {\n        definition.passThrough = true;\n      };\n    }\n\n    definitions.push(definition);\n    return chain;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for GET requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for HEAD requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for DELETE requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for POST requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for PUT requests.  For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for JSONP requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n  createShortMethods('when');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expect\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current expectation.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *  request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.expect = function(method, url, data, headers) {\n    var expectation = new MockHttpExpectation(method, url, data, headers);\n    expectations.push(expectation);\n    return {\n      respond: function(status, data, headers) {\n        expectation.response = createResponse(status, data, headers);\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for GET requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled. See #expect for more info.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for HEAD requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for DELETE requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for POST requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PUT requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPATCH\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PATCH requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for JSONP requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n  createShortMethods('expect');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#flush\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Flushes all pending requests using the trained responses.\n   *\n   * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,\n   *   all pending requests will be flushed. If there are no pending requests when the flush method\n   *   is called an exception is thrown (as this typically a sign of programming error).\n   */\n  $httpBackend.flush = function(count) {\n    if (!responses.length) throw Error('No pending request to flush !');\n\n    if (angular.isDefined(count)) {\n      while (count--) {\n        if (!responses.length) throw Error('No more pending request to flush !');\n        responses.shift()();\n      }\n    } else {\n      while (responses.length) {\n        responses.shift()();\n      }\n    }\n    $httpBackend.verifyNoOutstandingExpectation();\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingExpectation\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that all of the requests defined via the `expect` api were made. If any of the\n   * requests were not made, verifyNoOutstandingExpectation throws an exception.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyExpectations);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingExpectation = function() {\n    if (expectations.length) {\n      throw Error('Unsatisfied requests: ' + expectations.join(', '));\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingRequest\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that there are no outstanding requests that need to be flushed.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyNoOutstandingRequest);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingRequest = function() {\n    if (responses.length) {\n      throw Error('Unflushed requests: ' + responses.length);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#resetExpectations\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Resets all request expectations, but preserves all backend definitions. Typically, you would\n   * call resetExpectations during a multiple-phase test when you want to reuse the same instance of\n   * $httpBackend mock.\n   */\n  $httpBackend.resetExpectations = function() {\n    expectations.length = 0;\n    responses.length = 0;\n  };\n\n  return $httpBackend;\n\n\n  function createShortMethods(prefix) {\n    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {\n     $httpBackend[prefix + method] = function(url, headers) {\n       return $httpBackend[prefix](method, url, undefined, headers)\n     }\n    });\n\n    angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {\n      $httpBackend[prefix + method] = function(url, data, headers) {\n        return $httpBackend[prefix](method, url, data, headers)\n      }\n    });\n  }\n}\n\nfunction MockHttpExpectation(method, url, data, headers) {\n\n  this.data = data;\n  this.headers = headers;\n\n  this.match = function(m, u, d, h) {\n    if (method != m) return false;\n    if (!this.matchUrl(u)) return false;\n    if (angular.isDefined(d) && !this.matchData(d)) return false;\n    if (angular.isDefined(h) && !this.matchHeaders(h)) return false;\n    return true;\n  };\n\n  this.matchUrl = function(u) {\n    if (!url) return true;\n    if (angular.isFunction(url.test)) return url.test(u);\n    return url == u;\n  };\n\n  this.matchHeaders = function(h) {\n    if (angular.isUndefined(headers)) return true;\n    if (angular.isFunction(headers)) return headers(h);\n    return angular.equals(headers, h);\n  };\n\n  this.matchData = function(d) {\n    if (angular.isUndefined(data)) return true;\n    if (data && angular.isFunction(data.test)) return data.test(d);\n    if (data && !angular.isString(data)) return angular.toJson(data) == d;\n    return data == d;\n  };\n\n  this.toString = function() {\n    return method + ' ' + url;\n  };\n}\n\nfunction MockXhr() {\n\n  // hack for testing $http, $httpBackend\n  MockXhr.$$lastInstance = this;\n\n  this.open = function(method, url, async) {\n    this.$$method = method;\n    this.$$url = url;\n    this.$$async = async;\n    this.$$reqHeaders = {};\n    this.$$respHeaders = {};\n  };\n\n  this.send = function(data) {\n    this.$$data = data;\n  };\n\n  this.setRequestHeader = function(key, value) {\n    this.$$reqHeaders[key] = value;\n  };\n\n  this.getResponseHeader = function(name) {\n    // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last\n    var header = this.$$respHeaders[name];\n    if (header) return header;\n\n    name = angular.lowercase(name);\n    header = this.$$respHeaders[name];\n    if (header) return header;\n\n    header = undefined;\n    angular.forEach(this.$$respHeaders, function(headerVal, headerName) {\n      if (!header && angular.lowercase(headerName) == name) header = headerVal;\n    });\n    return header;\n  };\n\n  this.getAllResponseHeaders = function() {\n    var lines = [];\n\n    angular.forEach(this.$$respHeaders, function(value, key) {\n      lines.push(key + ': ' + value);\n    });\n    return lines.join('\\n');\n  };\n\n  this.abort = angular.noop;\n}\n\n\n/**\n * @ngdoc function\n * @name ngMock.$timeout\n * @description\n *\n * This service is just a simple decorator for {@link ng.$timeout $timeout} service\n * that adds a \"flush\" method.\n */\n\n/**\n * @ngdoc method\n * @name ngMock.$timeout#flush\n * @methodOf ngMock.$timeout\n * @description\n *\n * Flushes the queue of pending tasks.\n */\n\n/**\n *\n */\nangular.mock.$RootElementProvider = function() {\n  this.$get = function() {\n    return angular.element('<div ng-app></div>');\n  }\n};\n\n/**\n * @ngdoc overview\n * @name ngMock\n * @description\n *\n * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful\n * mocks to the {@link AUTO.$injector $injector}.\n */\nangular.module('ngMock', ['ng']).provider({\n  $browser: angular.mock.$BrowserProvider,\n  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,\n  $log: angular.mock.$LogProvider,\n  $httpBackend: angular.mock.$HttpBackendProvider,\n  $rootElement: angular.mock.$RootElementProvider\n}).config(function($provide) {\n  $provide.decorator('$timeout', function($delegate, $browser) {\n    $delegate.flush = function() {\n      $browser.defer.flush();\n    };\n    return $delegate;\n  });\n});\n\n\n/**\n * @ngdoc overview\n * @name ngMockE2E\n * @description\n *\n * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.\n * Currently there is only one mock present in this module -\n * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.\n */\nangular.module('ngMockE2E', ['ng']).config(function($provide) {\n  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);\n});\n\n/**\n * @ngdoc object\n * @name ngMockE2E.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of\n * applications that use the {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for unit testing please see\n * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.\n *\n * This implementation can be used to respond with static or dynamic responses via the `when` api\n * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the\n * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch\n * templates from a webserver).\n *\n * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application\n * is being developed with the real backend api replaced with a mock, it is often desirable for\n * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch\n * templates or static files from the webserver). To configure the backend with this behavior\n * use the `passThrough` request handler of `when` instead of `respond`.\n *\n * Additionally, we don't want to manually have to flush mocked out requests like we do during unit\n * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests\n * automatically, closely simulating the behavior of the XMLHttpRequest object.\n *\n * To setup the application to run with this http backend, you have to create a module that depends\n * on the `ngMockE2E` and your application modules and defines the fake backend:\n *\n * <pre>\n *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);\n *   myAppDev.run(function($httpBackend) {\n *     phones = [{name: 'phone1'}, {name: 'phone2'}];\n *\n *     // returns the current list of phones\n *     $httpBackend.whenGET('/phones').respond(phones);\n *\n *     // adds a new phone to the phones array\n *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {\n *       phones.push(angular.fromJSON(data));\n *     });\n *     $httpBackend.whenGET(/^\\/templates\\//).passThrough();\n *     //...\n *   });\n * </pre>\n *\n * Afterwards, bootstrap your app with this new module.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#when\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition.\n *\n * @param {string} method HTTP method.\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n *   object and returns true if the headers match the current definition.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n *\n *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n *    – The respond method takes a set of static data to be returned or a function that can return\n *    an array containing response status (number), response data (string) and response headers\n *    (Object).\n *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`\n *    handler, will be pass through to the real backend (an XHR request will be made to the\n *    server.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenGET\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for GET requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenHEAD\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for HEAD requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenDELETE\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for DELETE requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPOST\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for POST requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPUT\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PUT requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPATCH\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PATCH requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenJSONP\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for JSONP requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\nangular.mock.e2e = {};\nangular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];\n\n\nangular.mock.clearDataCache = function() {\n  var key,\n      cache = angular.element.cache;\n\n  for(key in cache) {\n    if (cache.hasOwnProperty(key)) {\n      var handle = cache[key].handle;\n\n      handle && angular.element(handle.elem).unbind();\n      delete cache[key];\n    }\n  }\n};\n\n\nwindow.jstestdriver && (function(window) {\n  /**\n   * Global method to output any number of objects into JSTD console. Useful for debugging.\n   */\n  window.dump = function() {\n    var args = [];\n    angular.forEach(arguments, function(arg) {\n      args.push(angular.mock.dump(arg));\n    });\n    jstestdriver.console.log.apply(jstestdriver.console, args);\n    if (window.console) {\n      window.console.log.apply(window.console, args);\n    }\n  };\n})(window);\n\n\nwindow.jasmine && (function(window) {\n\n  afterEach(function() {\n    var spec = getCurrentSpec();\n    var injector = spec.$injector;\n\n    spec.$injector = null;\n    spec.$modules = null;\n\n    if (injector) {\n      injector.get('$rootElement').unbind();\n      injector.get('$browser').pollFns.length = 0;\n    }\n\n    angular.mock.clearDataCache();\n\n    // clean up jquery's fragment cache\n    angular.forEach(angular.element.fragments, function(val, key) {\n      delete angular.element.fragments[key];\n    });\n\n    MockXhr.$$lastInstance = null;\n\n    angular.forEach(angular.callbacks, function(val, key) {\n      delete angular.callbacks[key];\n    });\n    angular.callbacks.counter = 0;\n  });\n\n  function getCurrentSpec() {\n    return jasmine.getEnv().currentSpec;\n  }\n\n  function isSpecRunning() {\n    var spec = getCurrentSpec();\n    return spec && spec.queue.running;\n  }\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.module\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * This function registers a module configuration code. It collects the configuration information\n   * which will be used when the injector is created by {@link angular.mock.inject inject}.\n   *\n   * See {@link angular.mock.inject inject} for usage example\n   *\n   * @param {...(string|Function)} fns any number of modules which are represented as string\n   *        aliases or as anonymous module initialization functions. The modules are used to\n   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.\n   */\n  window.module = angular.mock.module = function() {\n    var moduleFns = Array.prototype.slice.call(arguments, 0);\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      if (spec.$injector) {\n        throw Error('Injector already created, can not register a module!');\n      } else {\n        var modules = spec.$modules || (spec.$modules = []);\n        angular.forEach(moduleFns, function(module) {\n          modules.push(module);\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.inject\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * The inject function wraps a function into an injectable function. The inject() creates new\n   * instance of {@link AUTO.$injector $injector} per test, which is then used for\n   * resolving references.\n   *\n   * See also {@link angular.mock.module module}\n   *\n   * Example of what a typical jasmine tests looks like with the inject method.\n   * <pre>\n   *\n   *   angular.module('myApplicationModule', [])\n   *       .value('mode', 'app')\n   *       .value('version', 'v1.0.1');\n   *\n   *\n   *   describe('MyApp', function() {\n   *\n   *     // You need to load modules that you want to test,\n   *     // it loads only the \"ng\" module by default.\n   *     beforeEach(module('myApplicationModule'));\n   *\n   *\n   *     // inject() is used to inject arguments of all given functions\n   *     it('should provide a version', inject(function(mode, version) {\n   *       expect(version).toEqual('v1.0.1');\n   *       expect(mode).toEqual('app');\n   *     }));\n   *\n   *\n   *     // The inject and module method can also be used inside of the it or beforeEach\n   *     it('should override a version and test the new version is injected', function() {\n   *       // module() takes functions or strings (module aliases)\n   *       module(function($provide) {\n   *         $provide.value('version', 'overridden'); // override version here\n   *       });\n   *\n   *       inject(function(version) {\n   *         expect(version).toEqual('overridden');\n   *       });\n   *     ));\n   *   });\n   *\n   * </pre>\n   *\n   * @param {...Function} fns any number of functions which will be injected using the injector.\n   */\n  window.inject = angular.mock.inject = function() {\n    var blockFns = Array.prototype.slice.call(arguments, 0);\n    var errorForStack = new Error('Declaration Location');\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      var modules = spec.$modules || [];\n      modules.unshift('ngMock');\n      modules.unshift('ng');\n      var injector = spec.$injector;\n      if (!injector) {\n        injector = spec.$injector = angular.injector(modules);\n      }\n      for(var i = 0, ii = blockFns.length; i < ii; i++) {\n        try {\n          injector.invoke(blockFns[i] || angular.noop, this);\n        } catch (e) {\n          if(e.stack) e.stack +=  '\\n' + errorForStack.stack;\n          throw e;\n        } finally {\n          errorForStack = null;\n        }\n      }\n    }\n  };\n})(window);\n"
  },
  {
    "path": "chapter4/recipe4/test/lib/angular/angular-scenario.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Mar 21 12:46:34 2012 -0700\n */\n(function( window, undefined ) {\n'use strict';\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.7.2\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in array && array[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n\t\tvar exec,\n\t\t\tbulk = key == null,\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\n\t\t// Sets many values\n\t\tif ( key && typeof key === \"object\" ) {\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n\t\t\t}\n\t\t\tchainable = 1;\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = pass === undefined && jQuery.isFunction( value );\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations only iterate when executing function values\n\t\t\t\tif ( exec ) {\n\t\t\t\t\texec = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn exec.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\n\t\t\t\t// Otherwise they run against the entire set\n\t\t\t\t} else {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor (; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchainable = 1;\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfired = true;\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar length = list.length;\n\t\t\t\t\tadd( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory || memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tfragment,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tpixelMargin: true\n\t};\n\n\t// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead\n\tjQuery.boxModel = support.boxModel = (document.compatMode === \"CSS1Compat\");\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor ( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\tfragment.removeChild( div );\n\n\t// Null elements to avoid leaks in IE\n\tfragment = select = opt = div = input = null;\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tmarginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,\n\t\t\tpaddingMarginBorderVisibility, paddingMarginBorder,\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tconMarginTop = 1;\n\t\tpaddingMarginBorder = \"padding:0;margin:0;border:\";\n\t\tpositionTopLeftWidthHeight = \"position:absolute;top:0;left:0;width:1px;height:1px;\";\n\t\tpaddingMarginBorderVisibility = paddingMarginBorder + \"0;visibility:hidden;\";\n\t\tstyle = \"style='\" + positionTopLeftWidthHeight + paddingMarginBorder + \"5px solid #000;\";\n\t\thtml = \"<div \" + style + \"display:block;'><div style='\" + paddingMarginBorder + \"0;display:block;overflow:hidden;'></div></div>\" +\n\t\t\t\"<table \" + style + \"' cellpadding='0' cellspacing='0'>\" +\n\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = paddingMarginBorderVisibility + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td style='\" + paddingMarginBorder + \"0;display:none'></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName( \"td\" );\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t// gets computed margin-right based on width of container. For more\n\t\t// info see bug #3333\n\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tmarginDiv = document.createElement( \"div\" );\n\t\t\tmarginDiv.style.width = \"0\";\n\t\t\tmarginDiv.style.marginRight = \"0\";\n\t\t\tdiv.style.width = \"2px\";\n\t\t\tdiv.appendChild( marginDiv );\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\t// (IE < 8 does this)\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.width = div.style.padding = \"1px\";\n\t\t\tdiv.style.border = 0;\n\t\t\tdiv.style.overflow = \"hidden\";\n\t\t\tdiv.style.display = \"inline\";\n\t\t\tdiv.style.zoom = 1;\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.style.overflow = \"visible\";\n\t\t\tdiv.innerHTML = \"<div style='width:5px;'></div>\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\t\t}\n\n\t\tdiv.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;\n\t\tdiv.innerHTML = html;\n\n\t\touter = div.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.style.marginTop = \"1%\";\n\t\t\tsupport.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== \"1%\";\n\t\t}\n\n\t\tif ( typeof container.style.zoom !== \"undefined\" ) {\n\t\t\tcontainer.style.zoom = 1;\n\t\t}\n\n\t\tbody.removeChild( container );\n\t\tmarginDiv = div = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\treturn support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ internalKey ] : internalKey;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ internalKey ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( internalKey );\n\t\t\t} else {\n\t\t\t\telem[ internalKey ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, part, attr, name, l,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = elem.attributes;\n\t\t\t\t\tfor ( l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split( \".\", 2 );\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\t\tpart = parts[1] + \"!\";\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\tdata = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\tif ( data === undefined && elem ) {\n\t\t\t\t\tdata = jQuery.data( elem, key );\n\t\t\t\t\tdata = dataAttr( elem, key, data );\n\t\t\t\t}\n\n\t\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\t\tdata;\n\t\t\t}\n\n\t\t\tparts[1] = value;\n\t\t\tthis.each(function() {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.triggerHandler( \"setData\" + part, parts );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + part, parts );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, false );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\thooks = {};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( object );\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, l, isBool,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\t\t\tattrNames = value.toLowerCase().split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tisBool = rboolean.test( name );\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\t// Do not do this for boolean attributes (see #10870)\n\t\t\t\t\tif ( !isBool ) {\n\t\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\t}\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( isBool && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true,\n\t\tcoords: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = \"\" + value );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+)?\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\tvar attrs = elem.attributes || {};\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || (attrs.id || {}).value === m[2]) &&\n\t\t\t(!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tquick: selector && quickParse( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t ( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\told = null;\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\tspecial = jQuery.event.special[ event.type ] || {},\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n\t\t\t// Pregenerate a single jQuery object for reuse with .is()\n\t\t\tjqcur = jQuery(this);\n\t\t\tjqcur.context = this.ownerDocument || this;\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process events on disabled elements (#6911, #8165)\n\t\t\t\tif ( cur.disabled !== true ) {\n\t\t\t\t\tselMatch = {};\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tjqcur[0] = cur;\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\t\tselMatch[ sel ] = (\n\t\t\t\t\t\t\t\thandleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\tret;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\t\t\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\telem._change_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) { // && selector != null\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( var type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\n\t\t\tparts.push( m[1] );\n\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\t\t/* falls through */\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n// Expose origPOS\n// \"global\" as in regardless of relation to brackets/parens\nExpr.match.globalPOS = origPOS;\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry {\n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.globalPOS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\tPOS.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery.clean(arguments) );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tnull;\n\t\t\t}\n\n\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, function( i, elem ) {\n\t\t\t\t\tif ( elem.src ) {\n\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\turl: elem.src,\n\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\tdataType: \"script\"\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\n\t// IE blanks contents when cloning scripts\n\t} else if ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdest.text = src.text;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n\n\t// Clear flags for bubbling special change/submit events, they must\n\t// be reattached when the newly cloned events are first activated\n\tdest.removeAttribute( \"_submit_attached\" );\n\tdest.removeAttribute( \"_change_attached\" );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n\t// Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n\tvar div = document.createElement( \"div\" );\n\tsafeFragment.appendChild( div );\n\n\tdiv.innerHTML = elem.outerHTML;\n\treturn div.firstChild;\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t\tclone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ?\n\t\t\t\telem.cloneNode( true ) :\n\t\t\t\tshimCloneNode( elem );\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType, script, j,\n\t\t\t\tret = [];\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\"),\n\t\t\t\t\t\tsafeChildNodes = safeFragment.childNodes,\n\t\t\t\t\t\tremove;\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\n\t\t\t\t\t// Clear elements from DocumentFragment (safeFragment or otherwise)\n\t\t\t\t\t// to avoid hoarding elements. Fixes #11356\n\t\t\t\t\tif ( div ) {\n\t\t\t\t\t\tdiv.parentNode.removeChild( div );\n\n\t\t\t\t\t\t// Guard against -1 index exceptions in FF3.6\n\t\t\t\t\t\tif ( safeChildNodes.length > 0 ) {\n\t\t\t\t\t\t\tremove = safeChildNodes[ safeChildNodes.length - 1 ];\n\n\t\t\t\t\t\t\tif ( remove && remove.parentNode ) {\n\t\t\t\t\t\t\t\tremove.parentNode.removeChild( remove );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tscript = ret[i];\n\t\t\t\tif ( scripts && jQuery.nodeName( script, \"script\" ) && (!script.type || rscriptType.test( script.type )) ) {\n\t\t\t\t\tscripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( script.nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( script.getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( script );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnum = /^[\\-+]?(?:\\d*\\.)?\\d+$/i,\n\trnumnonpx = /^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\trmargin = /^margin/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\n\t// order is important!\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\treturn jQuery.access( this, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t}, name, value, arguments.length > 1 );\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {},\n\t\t\tret, name;\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// DEPRECATED in 1.3, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle, width,\n\t\t\tstyle = elem.style;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( (defaultView = elem.ownerDocument.defaultView) &&\n\t\t\t\t(computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// WebKit uses \"computed value (percentage if specified)\" instead of \"used value\" for margins\n\t\t// which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {\n\t\t\twidth = style.width;\n\t\t\tstyle.width = ret;\n\t\t\tret = computedStyle.width;\n\t\t\tstyle.width = width;\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( rnumnonpx.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\ti = name === \"width\" ? 1 : 0,\n\t\tlen = 4;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tfor ( ; i < len; i += 2 ) {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ];\n\t}\n\n\t// Computed unit is not pixels. Stop here and return.\n\tif ( rnumnonpx.test(val) ) {\n\t\treturn val;\n\t}\n\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tfor ( ; i < len; i += 2 ) {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val + \"px\";\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\treturn jQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\treturn rnum.test( value ) ?\n\t\t\t\tvalue + \"px\" :\n\t\t\t\tvalue;\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\treturn curCSS( elem, \"margin-right\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i,\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n\t\t\t\texpanded = {};\n\n\t\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n});\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = ( typeof s.data === \"string\" ) && /^application\\/x\\-www\\-form\\-urlencoded/.test( s.contentType );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t} catch( _ ) {\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( (display === \"\" && jQuery.css(elem, \"display\") === \"none\") ||\n\t\t\t\t\t\t!jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e, hooks, replace,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\t// first pass over propertys to expand / normalize\n\t\t\tfor ( p in prop ) {\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tif ( ( hooks = jQuery.cssHooks[ name ] ) && \"expand\" in hooks ) {\n\t\t\t\t\treplace = hooks.expand( prop[ name ] );\n\t\t\t\t\tdelete prop[ name ];\n\n\t\t\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t\t\t// also - reusing 'p' from above because we have the correct \"name\"\n\t\t\t\t\tfor ( p in replace ) {\n\t\t\t\t\t\tif ( ! ( p in prop ) ) {\n\t\t\t\t\t\t\tprop[ p ] = replace[ p ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( name in prop ) {\n\t\t\t\tval = prop[ name ];\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, index ) {\n\t\t\t\tvar hooks = data[ index ];\n\t\t\t\tjQuery.removeData( elem, index, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n\t\t\t\tstopQueue( this, data, index );\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ index ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ index ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p ) {\n\t\t\treturn p;\n\t\t},\n\t\tswing: function( p ) {\n\t\t\treturn ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tif ( self.options.hide ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t\t} else if ( self.options.show ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.end );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Ensure props that can't be negative don't go there on undershoot easing\njQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {\n\t// exclude marginTop, marginLeft, marginBottom and marginRight from this list\n\tif ( prop.indexOf( \"margin\" ) ) {\n\t\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( jQuery.support.boxModel ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar getOffset,\n\trtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tgetOffset = function( elem, doc, docElem, box ) {\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow( doc ),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tgetOffset = function( elem, doc, docElem ) {\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar elem = this[0],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn null;\n\t}\n\n\tif ( elem === doc.body ) {\n\t\treturn jQuery.offset.bodyOffset( elem );\n\t}\n\n\treturn getOffset( elem, doc, doc.documentElement );\n};\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t top ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tvar clientProp = \"client\" + name,\n\t\tscrollProp = \"scroll\" + name,\n\t\toffsetProp = \"offset\" + name;\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( value ) {\n\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\tvar doc, docElemProp, orig, ret;\n\n\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\t\tdoc = elem.document;\n\t\t\t\tdocElemProp = doc.documentElement[ clientProp ];\n\t\t\t\treturn jQuery.support.boxModel && docElemProp ||\n\t\t\t\t\tdoc.body && doc.body[ clientProp ] || docElemProp;\n\t\t\t}\n\n\t\t\t// Get document width or height\n\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t// when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]\n\t\t\t\t// so we can't use max, as it'll choose the incorrect offset[Width/Height]\n\t\t\t\t// instead we use the correct client[Width/Height]\n\t\t\t\t// support:IE6\n\t\t\t\tif ( doc[ clientProp ] >= doc[ scrollProp ] ) {\n\t\t\t\t\treturn doc[ clientProp ];\n\t\t\t\t}\n\n\t\t\t\treturn Math.max(\n\t\t\t\t\telem.body[ scrollProp ], doc[ scrollProp ],\n\t\t\t\t\telem.body[ offsetProp ], doc[ offsetProp ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get width or height on the element\n\t\t\tif ( value === undefined ) {\n\t\t\t\torig = jQuery.css( elem, type );\n\t\t\t\tret = parseFloat( orig );\n\t\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\t\t\t}\n\n\t\t\t// Set the width or height on the element\n\t\t\tjQuery( elem ).css( type, value );\n\t\t}, type, value, arguments.length, null );\n\t};\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );\n/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document){\n  var _jQuery = window.jQuery.noConflict(true);\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n\n/**\n * Setup file for the Scenario.\n * Must be first in the compilation/bootstrap list.\n */\n\n// Public namespace\nangular.scenario = angular.scenario || {};\n\n/**\n * Defines a new output format.\n *\n * @param {string} name the name of the new output format\n * @param {function()} fn function(context, runner) that generates the output\n */\nangular.scenario.output = angular.scenario.output || function(name, fn) {\n  angular.scenario.output[name] = fn;\n};\n\n/**\n * Defines a new DSL statement. If your factory function returns a Future\n * it's returned, otherwise the result is assumed to be a map of functions\n * for chaining. Chained functions are subject to the same rules.\n *\n * Note: All functions on the chain are bound to the chain scope so values\n *   set on \"this\" in your statement function are available in the chained\n *   functions.\n *\n * @param {string} name The name of the statement\n * @param {function()} fn Factory function(), return a function for\n *  the statement.\n */\nangular.scenario.dsl = angular.scenario.dsl || function(name, fn) {\n  angular.scenario.dsl[name] = function() {\n    function executeStatement(statement, args) {\n      var result = statement.apply(this, args);\n      if (angular.isFunction(result) || result instanceof angular.scenario.Future)\n        return result;\n      var self = this;\n      var chain = angular.extend({}, result);\n      angular.forEach(chain, function(value, name) {\n        if (angular.isFunction(value)) {\n          chain[name] = function() {\n            return executeStatement.call(self, value, arguments);\n          };\n        } else {\n          chain[name] = value;\n        }\n      });\n      return chain;\n    }\n    var statement = fn.apply(this, arguments);\n    return function() {\n      return executeStatement.call(this, statement, arguments);\n    };\n  };\n};\n\n/**\n * Defines a new matcher for use with the expects() statement. The value\n * this.actual (like in Jasmine) is available in your matcher to compare\n * against. Your function should return a boolean. The future is automatically\n * created for you.\n *\n * @param {string} name The name of the matcher\n * @param {function()} fn The matching function(expected).\n */\nangular.scenario.matcher = angular.scenario.matcher || function(name, fn) {\n  angular.scenario.matcher[name] = function(expected) {\n    var prefix = 'expect ' + this.future.name + ' ';\n    if (this.inverse) {\n      prefix += 'not ';\n    }\n    var self = this;\n    this.addFuture(prefix + name + ' ' + angular.toJson(expected),\n      function(done) {\n        var error;\n        self.actual = self.future.value;\n        if ((self.inverse && fn.call(self, expected)) ||\n            (!self.inverse && !fn.call(self, expected))) {\n          error = 'expected ' + angular.toJson(expected) +\n            ' but was ' + angular.toJson(self.actual);\n        }\n        done(error);\n    });\n  };\n};\n\n/**\n * Initialize the scenario runner and run !\n *\n * Access global window and document object\n * Access $runner through closure\n *\n * @param {Object=} config Config options\n */\nangular.scenario.setUpAndRun = function(config) {\n  var href = window.location.href;\n  var body = _jQuery(document.body);\n  var output = [];\n  var objModel = new angular.scenario.ObjectModel($runner);\n\n  if (config && config.scenario_output) {\n    output = config.scenario_output.split(',');\n  }\n\n  angular.forEach(angular.scenario.output, function(fn, name) {\n    if (!output.length || indexOf(output,name) != -1) {\n      var context = body.append('<div></div>').find('div:last');\n      context.attr('id', name);\n      fn.call({}, context, $runner, objModel);\n    }\n  });\n\n  if (!/^http/.test(href) && !/^https/.test(href)) {\n    body.append('<p id=\"system-error\"></p>');\n    body.find('#system-error').text(\n      'Scenario runner must be run using http or https. The protocol ' +\n      href.split(':')[0] + ':// is not supported.'\n    );\n    return;\n  }\n\n  var appFrame = body.append('<div id=\"application\"></div>').find('#application');\n  var application = new angular.scenario.Application(appFrame);\n\n  $runner.on('RunnerEnd', function() {\n    appFrame.css('display', 'none');\n    appFrame.find('iframe').attr('src', 'about:blank');\n  });\n\n  $runner.on('RunnerError', function(error) {\n    if (window.console) {\n      console.log(formatException(error));\n    } else {\n      // Do something for IE\n      alert(error);\n    }\n  });\n\n  $runner.run(application);\n};\n\n/**\n * Iterates through list with iterator function that must call the\n * continueFunction to continute iterating.\n *\n * @param {Array} list list to iterate over\n * @param {function()} iterator Callback function(value, continueFunction)\n * @param {function()} done Callback function(error, result) called when\n *   iteration finishes or an error occurs.\n */\nfunction asyncForEach(list, iterator, done) {\n  var i = 0;\n  function loop(error, index) {\n    if (index && index > i) {\n      i = index;\n    }\n    if (error || i >= list.length) {\n      done(error);\n    } else {\n      try {\n        iterator(list[i++], loop);\n      } catch (e) {\n        done(e);\n      }\n    }\n  }\n  loop();\n}\n\n/**\n * Formats an exception into a string with the stack trace, but limits\n * to a specific line length.\n *\n * @param {Object} error The exception to format, can be anything throwable\n * @param {Number=} [maxStackLines=5] max lines of the stack trace to include\n *  default is 5.\n */\nfunction formatException(error, maxStackLines) {\n  maxStackLines = maxStackLines || 5;\n  var message = error.toString();\n  if (error.stack) {\n    var stack = error.stack.split('\\n');\n    if (stack[0].indexOf(message) === -1) {\n      maxStackLines++;\n      stack.unshift(error.message);\n    }\n    message = stack.slice(0, maxStackLines).join('\\n');\n  }\n  return message;\n}\n\n/**\n * Returns a function that gets the file name and line number from a\n * location in the stack if available based on the call site.\n *\n * Note: this returns another function because accessing .stack is very\n * expensive in Chrome.\n *\n * @param {Number} offset Number of stack lines to skip\n */\nfunction callerFile(offset) {\n  var error = new Error();\n\n  return function() {\n    var line = (error.stack || '').split('\\n')[offset];\n\n    // Clean up the stack trace line\n    if (line) {\n      if (line.indexOf('@') !== -1) {\n        // Firefox\n        line = line.substring(line.indexOf('@')+1);\n      } else {\n        // Chrome\n        line = line.substring(line.indexOf('(')+1).replace(')', '');\n      }\n    }\n\n    return line || '';\n  };\n}\n\n/**\n * Triggers a browser event. Attempts to choose the right event if one is\n * not specified.\n *\n * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement\n * @param {string} type Optional event type.\n * @param {Array.<string>=} keys Optional list of pressed keys\n *        (valid values: 'alt', 'meta', 'shift', 'ctrl')\n */\nfunction browserTrigger(element, type, keys) {\n  if (element && !element.nodeName) element = element[0];\n  if (!element) return;\n  if (!type) {\n    type = {\n        'text':            'change',\n        'textarea':        'change',\n        'hidden':          'change',\n        'password':        'change',\n        'button':          'click',\n        'submit':          'click',\n        'reset':           'click',\n        'image':           'click',\n        'checkbox':        'click',\n        'radio':           'click',\n        'select-one':      'change',\n        'select-multiple': 'change'\n    }[lowercase(element.type)] || 'click';\n  }\n  if (lowercase(nodeName_(element)) == 'option') {\n    element.parentNode.value = element.value;\n    element = element.parentNode;\n    type = 'change';\n  }\n\n  keys = keys || [];\n  function pressed(key) {\n    return indexOf(keys, key) !== -1;\n  }\n\n  if (msie < 9) {\n    switch(element.type) {\n      case 'radio':\n      case 'checkbox':\n        element.checked = !element.checked;\n        break;\n    }\n    // WTF!!! Error: Unspecified error.\n    // Don't know why, but some elements when detached seem to be in inconsistent state and\n    // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)\n    // forcing the browser to compute the element position (by reading its CSS)\n    // puts the element in consistent state.\n    element.style.posLeft;\n\n    // TODO(vojta): create event objects with pressed keys to get it working on IE<9\n    var ret = element.fireEvent('on' + type);\n    if (lowercase(element.type) == 'submit') {\n      while(element) {\n        if (lowercase(element.nodeName) == 'form') {\n          element.fireEvent('onsubmit');\n          break;\n        }\n        element = element.parentNode;\n      }\n    }\n    return ret;\n  } else {\n    var evnt = document.createEvent('MouseEvents'),\n        originalPreventDefault = evnt.preventDefault,\n        iframe = _jQuery('#application iframe')[0],\n        appWindow = iframe ? iframe.contentWindow : window,\n        fakeProcessDefault = true,\n        finalProcessDefault,\n        angular = appWindow.angular || {};\n\n    // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208\n    angular['ff-684208-preventDefault'] = false;\n    evnt.preventDefault = function() {\n      fakeProcessDefault = false;\n      return originalPreventDefault.apply(evnt, arguments);\n    };\n\n    evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, pressed('ctrl'), pressed('alt'),\n                        pressed('shift'), pressed('meta'), 0, element);\n\n    element.dispatchEvent(evnt);\n    finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);\n\n    delete angular['ff-684208-preventDefault'];\n\n    return finalProcessDefault;\n  }\n}\n\n/**\n * Don't use the jQuery trigger method since it works incorrectly.\n *\n * jQuery notifies listeners and then changes the state of a checkbox and\n * does not create a real browser event. A real click changes the state of\n * the checkbox and then notifies listeners.\n *\n * To work around this we instead use our own handler that fires a real event.\n */\n(function(fn){\n  var parentTrigger = fn.trigger;\n  fn.trigger = function(type) {\n    if (/(click|change|keydown|blur|input)/.test(type)) {\n      var processDefaults = [];\n      this.each(function(index, node) {\n        processDefaults.push(browserTrigger(node, type));\n      });\n\n      // this is not compatible with jQuery - we return an array of returned values,\n      // so that scenario runner know whether JS code has preventDefault() of the event or not...\n      return processDefaults;\n    }\n    return parentTrigger.apply(this, arguments);\n  };\n})(_jQuery.fn);\n\n/**\n * Finds all bindings with the substring match of name and returns an\n * array of their values.\n *\n * @param {string} bindExp The name to match\n * @return {Array.<string>} String of binding values\n */\n_jQuery.fn.bindings = function(windowJquery, bindExp) {\n  var result = [], match,\n      bindSelector = '.ng-binding:visible';\n  if (angular.isString(bindExp)) {\n    bindExp = bindExp.replace(/\\s/g, '');\n    match = function (actualExp) {\n      if (actualExp) {\n        actualExp = actualExp.replace(/\\s/g, '');\n        if (actualExp == bindExp) return true;\n        if (actualExp.indexOf(bindExp) == 0) {\n          return actualExp.charAt(bindExp.length) == '|';\n        }\n      }\n    }\n  } else if (bindExp) {\n    match = function(actualExp) {\n      return actualExp && bindExp.exec(actualExp);\n    }\n  } else {\n    match = function(actualExp) {\n      return !!actualExp;\n    };\n  }\n  var selection = this.find(bindSelector);\n  if (this.is(bindSelector)) {\n    selection = selection.add(this);\n  }\n\n  function push(value) {\n    if (value == undefined) {\n      value = '';\n    } else if (typeof value != 'string') {\n      value = angular.toJson(value);\n    }\n    result.push('' + value);\n  }\n\n  selection.each(function() {\n    var element = windowJquery(this),\n        binding;\n    if (binding = element.data('$binding')) {\n      if (typeof binding == 'string') {\n        if (match(binding)) {\n          push(element.scope().$eval(binding));\n        }\n      } else {\n        if (!angular.isArray(binding)) {\n          binding = [binding];\n        }\n        for(var fns, j=0, jj=binding.length;  j<jj; j++) {\n          fns = binding[j];\n          if (fns.parts) {\n            fns = fns.parts;\n          } else {\n            fns = [fns];\n          }\n          for (var scope, fn, i = 0, ii = fns.length; i < ii; i++) {\n            if(match((fn = fns[i]).exp)) {\n              push(fn(scope = scope || element.scope()));\n            }\n          }\n        }\n      }\n    }\n  });\n  return result;\n};\n\n/**\n * Represents the application currently being tested and abstracts usage\n * of iframes or separate windows.\n *\n * @param {Object} context jQuery wrapper around HTML context.\n */\nangular.scenario.Application = function(context) {\n  this.context = context;\n  context.append(\n    '<h2>Current URL: <a href=\"about:blank\">None</a></h2>' +\n    '<div id=\"test-frames\"></div>'\n  );\n};\n\n/**\n * Gets the jQuery collection of frames. Don't use this directly because\n * frames may go stale.\n *\n * @private\n * @return {Object} jQuery collection\n */\nangular.scenario.Application.prototype.getFrame_ = function() {\n  return this.context.find('#test-frames iframe:last');\n};\n\n/**\n * Gets the window of the test runner frame. Always favor executeAction()\n * instead of this method since it prevents you from getting a stale window.\n *\n * @private\n * @return {Object} the window of the frame\n */\nangular.scenario.Application.prototype.getWindow_ = function() {\n  var contentWindow = this.getFrame_().prop('contentWindow');\n  if (!contentWindow)\n    throw 'Frame window is not accessible.';\n  return contentWindow;\n};\n\n/**\n * Changes the location of the frame.\n *\n * @param {string} url The URL. If it begins with a # then only the\n *   hash of the page is changed.\n * @param {function()} loadFn function($window, $document) Called when frame loads.\n * @param {function()} errorFn function(error) Called if any error when loading.\n */\nangular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorFn) {\n  var self = this;\n  var frame = this.getFrame_();\n  //TODO(esprehn): Refactor to use rethrow()\n  errorFn = errorFn || function(e) { throw e; };\n  if (url === 'about:blank') {\n    errorFn('Sandbox Error: Navigating to about:blank is not allowed.');\n  } else if (url.charAt(0) === '#') {\n    url = frame.attr('src').split('#')[0] + url;\n    frame.attr('src', url);\n    this.executeAction(loadFn);\n  } else {\n    frame.remove();\n    this.context.find('#test-frames').append('<iframe>');\n    frame = this.getFrame_();\n    frame.load(function() {\n      frame.unbind();\n      try {\n        self.executeAction(loadFn);\n      } catch (e) {\n        errorFn(e);\n      }\n    }).attr('src', url);\n  }\n  this.context.find('> h2 a').attr('href', url).text(url);\n};\n\n/**\n * Executes a function in the context of the tested application. Will wait\n * for all pending angular xhr requests before executing.\n *\n * @param {function()} action The callback to execute. function($window, $document)\n *  $document is a jQuery wrapped document.\n */\nangular.scenario.Application.prototype.executeAction = function(action) {\n  var self = this;\n  var $window = this.getWindow_();\n  if (!$window.document) {\n    throw 'Sandbox Error: Application document not accessible.';\n  }\n  if (!$window.angular) {\n    return action.call(this, $window, _jQuery($window.document));\n  }\n  angularInit($window.document, function(element) {\n    var $injector = $window.angular.element(element).injector();\n    var $element = _jQuery(element);\n\n    $element.injector = function() {\n      return $injector;\n    };\n\n    $injector.invoke(function($browser){\n      $browser.notifyWhenNoOutstandingRequests(function() {\n        action.call(self, $window, $element);\n      });\n    });\n  });\n};\n\n/**\n * The representation of define blocks. Don't used directly, instead use\n * define() in your tests.\n *\n * @param {string} descName Name of the block\n * @param {Object} parent describe or undefined if the root.\n */\nangular.scenario.Describe = function(descName, parent) {\n  this.only = parent && parent.only;\n  this.beforeEachFns = [];\n  this.afterEachFns = [];\n  this.its = [];\n  this.children = [];\n  this.name = descName;\n  this.parent = parent;\n  this.id = angular.scenario.Describe.id++;\n\n  /**\n   * Calls all before functions.\n   */\n  var beforeEachFns = this.beforeEachFns;\n  this.setupBefore = function() {\n    if (parent) parent.setupBefore.call(this);\n    angular.forEach(beforeEachFns, function(fn) { fn.call(this); }, this);\n  };\n\n  /**\n   * Calls all after functions.\n   */\n  var afterEachFns = this.afterEachFns;\n  this.setupAfter  = function() {\n    angular.forEach(afterEachFns, function(fn) { fn.call(this); }, this);\n    if (parent) parent.setupAfter.call(this);\n  };\n};\n\n// Shared Unique ID generator for every describe block\nangular.scenario.Describe.id = 0;\n\n// Shared Unique ID generator for every it (spec)\nangular.scenario.Describe.specId = 0;\n\n/**\n * Defines a block to execute before each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.beforeEach = function(body) {\n  this.beforeEachFns.push(body);\n};\n\n/**\n * Defines a block to execute after each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.afterEach = function(body) {\n  this.afterEachFns.push(body);\n};\n\n/**\n * Creates a new describe block that's a child of this one.\n *\n * @param {string} name Name of the block. Appended to the parent block's name.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.describe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Same as describe() but makes ddescribe blocks the only to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.ddescribe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  child.only = true;\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Use to disable a describe block.\n */\nangular.scenario.Describe.prototype.xdescribe = angular.noop;\n\n/**\n * Defines a test.\n *\n * @param {string} name Name of the test.\n * @param {function()} vody Body of the block.\n */\nangular.scenario.Describe.prototype.it = function(name, body) {\n  this.its.push({\n    id: angular.scenario.Describe.specId++,\n    definition: this,\n    only: this.only,\n    name: name,\n    before: this.setupBefore,\n    body: body,\n    after: this.setupAfter\n  });\n};\n\n/**\n * Same as it() but makes iit tests the only test to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.iit = function(name, body) {\n  this.it.apply(this, arguments);\n  this.its[this.its.length-1].only = true;\n};\n\n/**\n * Use to disable a test block.\n */\nangular.scenario.Describe.prototype.xit = angular.noop;\n\n/**\n * Gets an array of functions representing all the tests (recursively).\n * that can be executed with SpecRunner's.\n *\n * @return {Array<Object>} Array of it blocks {\n *   definition : Object // parent Describe\n *   only: boolean\n *   name: string\n *   before: Function\n *   body: Function\n *   after: Function\n *  }\n */\nangular.scenario.Describe.prototype.getSpecs = function() {\n  var specs = arguments[0] || [];\n  angular.forEach(this.children, function(child) {\n    child.getSpecs(specs);\n  });\n  angular.forEach(this.its, function(it) {\n    specs.push(it);\n  });\n  var only = [];\n  angular.forEach(specs, function(it) {\n    if (it.only) {\n      only.push(it);\n    }\n  });\n  return (only.length && only) || specs;\n};\n\n/**\n * A future action in a spec.\n *\n * @param {string} name of the future action\n * @param {function()} future callback(error, result)\n * @param {function()} Optional. function that returns the file/line number.\n */\nangular.scenario.Future = function(name, behavior, line) {\n  this.name = name;\n  this.behavior = behavior;\n  this.fulfilled = false;\n  this.value = undefined;\n  this.parser = angular.identity;\n  this.line = line || function() { return ''; };\n};\n\n/**\n * Executes the behavior of the closure.\n *\n * @param {function()} doneFn Callback function(error, result)\n */\nangular.scenario.Future.prototype.execute = function(doneFn) {\n  var self = this;\n  this.behavior(function(error, result) {\n    self.fulfilled = true;\n    if (result) {\n      try {\n        result = self.parser(result);\n      } catch(e) {\n        error = e;\n      }\n    }\n    self.value = error || result;\n    doneFn(error, result);\n  });\n};\n\n/**\n * Configures the future to convert it's final with a function fn(value)\n *\n * @param {function()} fn function(value) that returns the parsed value\n */\nangular.scenario.Future.prototype.parsedWith = function(fn) {\n  this.parser = fn;\n  return this;\n};\n\n/**\n * Configures the future to parse it's final value from JSON\n * into objects.\n */\nangular.scenario.Future.prototype.fromJson = function() {\n  return this.parsedWith(angular.fromJson);\n};\n\n/**\n * Configures the future to convert it's final value from objects\n * into JSON.\n */\nangular.scenario.Future.prototype.toJson = function() {\n  return this.parsedWith(angular.toJson);\n};\n\n/**\n * Maintains an object tree from the runner events.\n *\n * @param {Object} runner The scenario Runner instance to connect to.\n *\n * TODO(esprehn): Every output type creates one of these, but we probably\n *  want one global shared instance. Need to handle events better too\n *  so the HTML output doesn't need to do spec model.getSpec(spec.id)\n *  silliness.\n *\n * TODO(vojta) refactor on, emit methods (from all objects) - use inheritance\n */\nangular.scenario.ObjectModel = function(runner) {\n  var self = this;\n\n  this.specMap = {};\n  this.listeners = [];\n  this.value = {\n    name: '',\n    children: {}\n  };\n\n  runner.on('SpecBegin', function(spec) {\n    var block = self.value,\n        definitions = [];\n\n    angular.forEach(self.getDefinitionPath(spec), function(def) {\n      if (!block.children[def.name]) {\n        block.children[def.name] = {\n          id: def.id,\n          name: def.name,\n          children: {},\n          specs: {}\n        };\n      }\n      block = block.children[def.name];\n      definitions.push(def.name);\n    });\n\n    var it = self.specMap[spec.id] =\n             block.specs[spec.name] =\n             new angular.scenario.ObjectModel.Spec(spec.id, spec.name, definitions);\n\n    // forward the event\n    self.emit('SpecBegin', it);\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var it = self.getSpec(spec.id);\n    it.status = 'error';\n    it.error = error;\n\n    // forward the event\n    self.emit('SpecError', it, error);\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    complete(it);\n\n    // forward the event\n    self.emit('SpecEnd', it);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var it = self.getSpec(spec.id);\n    var step = new angular.scenario.ObjectModel.Step(step.name);\n    it.steps.push(step);\n\n    // forward the event\n    self.emit('StepBegin', it, step);\n  });\n\n  runner.on('StepEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    var step = it.getLastStep();\n    if (step.name !== step.name)\n      throw 'Events fired in the wrong order. Step names don\\'t match.';\n    complete(step);\n\n    // forward the event\n    self.emit('StepEnd', it, step);\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('failure', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepFailure', it, modelStep, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('error', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepError', it, modelStep, error);\n  });\n\n  runner.on('RunnerBegin', function() {\n    self.emit('RunnerBegin');\n  });\n  runner.on('RunnerEnd', function() {\n    self.emit('RunnerEnd');\n  });\n\n  function complete(item) {\n    item.endTime = new Date().getTime();\n    item.duration = item.endTime - item.startTime;\n    item.status = item.status || 'success';\n  }\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName Name of the event to add a handler for\n * @param {function()} listener Function that will be called when event is fired\n */\nangular.scenario.ObjectModel.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.ObjectModel.prototype.emit = function(eventName) {\n  var self = this,\n      args = Array.prototype.slice.call(arguments, 1),\n      eventName = eventName.toLowerCase();\n\n  if (this.listeners[eventName]) {\n    angular.forEach(this.listeners[eventName], function(listener) {\n      listener.apply(self, args);\n    });\n  }\n};\n\n/**\n * Computes the path of definition describe blocks that wrap around\n * this spec.\n *\n * @param spec Spec to compute the path for.\n * @return {Array<Describe>} The describe block path\n */\nangular.scenario.ObjectModel.prototype.getDefinitionPath = function(spec) {\n  var path = [];\n  var currentDefinition = spec.definition;\n  while (currentDefinition && currentDefinition.name) {\n    path.unshift(currentDefinition);\n    currentDefinition = currentDefinition.parent;\n  }\n  return path;\n};\n\n/**\n * Gets a spec by id.\n *\n * @param {string} The id of the spec to get the object for.\n * @return {Object} the Spec instance\n */\nangular.scenario.ObjectModel.prototype.getSpec = function(id) {\n  return this.specMap[id];\n};\n\n/**\n * A single it block.\n *\n * @param {string} id Id of the spec\n * @param {string} name Name of the spec\n * @param {Array<string>=} definitionNames List of all describe block names that wrap this spec\n */\nangular.scenario.ObjectModel.Spec = function(id, name, definitionNames) {\n  this.id = id;\n  this.name = name;\n  this.startTime = new Date().getTime();\n  this.steps = [];\n  this.fullDefinitionName = (definitionNames || []).join(' ');\n};\n\n/**\n * Adds a new step to the Spec.\n *\n * @param {string} step Name of the step (really name of the future)\n * @return {Object} the added step\n */\nangular.scenario.ObjectModel.Spec.prototype.addStep = function(name) {\n  var step = new angular.scenario.ObjectModel.Step(name);\n  this.steps.push(step);\n  return step;\n};\n\n/**\n * Gets the most recent step.\n *\n * @return {Object} the step\n */\nangular.scenario.ObjectModel.Spec.prototype.getLastStep = function() {\n  return this.steps[this.steps.length-1];\n};\n\n/**\n * Set status of the Spec from given Step\n *\n * @param {angular.scenario.ObjectModel.Step} step\n */\nangular.scenario.ObjectModel.Spec.prototype.setStatusFromStep = function(step) {\n  if (!this.status || step.status == 'error') {\n    this.status = step.status;\n    this.error = step.error;\n    this.line = step.line;\n  }\n};\n\n/**\n * A single step inside a Spec.\n *\n * @param {string} step Name of the step\n */\nangular.scenario.ObjectModel.Step = function(name) {\n  this.name = name;\n  this.startTime = new Date().getTime();\n};\n\n/**\n * Helper method for setting all error status related properties\n *\n * @param {string} status\n * @param {string} error\n * @param {string} line\n */\nangular.scenario.ObjectModel.Step.prototype.setErrorStatus = function(status, error, line) {\n  this.status = status;\n  this.error = error;\n  this.line = line;\n};\n\n/**\n * Runner for scenarios\n *\n * Has to be initialized before any test is loaded,\n * because it publishes the API into window (global space).\n */\nangular.scenario.Runner = function($window) {\n  this.listeners = [];\n  this.$window = $window;\n  this.rootDescribe = new angular.scenario.Describe();\n  this.currentDescribe = this.rootDescribe;\n  this.api = {\n    it: this.it,\n    iit: this.iit,\n    xit: angular.noop,\n    describe: this.describe,\n    ddescribe: this.ddescribe,\n    xdescribe: angular.noop,\n    beforeEach: this.beforeEach,\n    afterEach: this.afterEach\n  };\n  angular.forEach(this.api, angular.bind(this, function(fn, key) {\n    this.$window[key] = angular.bind(this, fn);\n  }));\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.Runner.prototype.emit = function(eventName) {\n  var self = this;\n  var args = Array.prototype.slice.call(arguments, 1);\n  eventName = eventName.toLowerCase();\n  if (!this.listeners[eventName])\n    return;\n  angular.forEach(this.listeners[eventName], function(listener) {\n    listener.apply(self, args);\n  });\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName The name of the event to add a handler for\n * @param {string} listener The fn(...) that takes the extra arguments from emit()\n */\nangular.scenario.Runner.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Defines a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.describe = function(name, body) {\n  var self = this;\n  this.currentDescribe.describe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Same as describe, but makes ddescribe the only blocks to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.ddescribe = function(name, body) {\n  var self = this;\n  this.currentDescribe.ddescribe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Defines a test in a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.it = function(name, body) {\n  this.currentDescribe.it(name, body);\n};\n\n/**\n * Same as it, but makes iit tests the only tests to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.iit = function(name, body) {\n  this.currentDescribe.iit(name, body);\n};\n\n/**\n * Defines a function to be called before each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.beforeEach = function(body) {\n  this.currentDescribe.beforeEach(body);\n};\n\n/**\n * Defines a function to be called after each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.afterEach = function(body) {\n  this.currentDescribe.afterEach(body);\n};\n\n/**\n * Creates a new spec runner.\n *\n * @private\n * @param {Object} scope parent scope\n */\nangular.scenario.Runner.prototype.createSpecRunner_ = function(scope) {\n  var child = scope.$new();\n  var Cls = angular.scenario.SpecRunner;\n\n  // Export all the methods to child scope manually as now we don't mess controllers with scopes\n  // TODO(vojta): refactor scenario runner so that these objects are not tightly coupled as current\n  for (var name in Cls.prototype)\n    child[name] = angular.bind(child, Cls.prototype[name]);\n\n  Cls.call(child);\n  return child;\n};\n\n/**\n * Runs all the loaded tests with the specified runner class on the\n * provided application.\n *\n * @param {angular.scenario.Application} application App to remote control.\n */\nangular.scenario.Runner.prototype.run = function(application) {\n  var self = this;\n  var $root = angular.injector(['ng']).get('$rootScope');\n  angular.extend($root, this);\n  angular.forEach(angular.scenario.Runner.prototype, function(fn, name) {\n    $root[name] = angular.bind(self, fn);\n  });\n  $root.application = application;\n  $root.emit('RunnerBegin');\n  asyncForEach(this.rootDescribe.getSpecs(), function(spec, specDone) {\n    var dslCache = {};\n    var runner = self.createSpecRunner_($root);\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      dslCache[key] = fn.call($root);\n    });\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      self.$window[key] = function() {\n        var line = callerFile(3);\n        var scope = runner.$new();\n\n        // Make the dsl accessible on the current chain\n        scope.dsl = {};\n        angular.forEach(dslCache, function(fn, key) {\n          scope.dsl[key] = function() {\n            return dslCache[key].apply(scope, arguments);\n          };\n        });\n\n        // Make these methods work on the current chain\n        scope.addFuture = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFuture.apply(scope, arguments);\n        };\n        scope.addFutureAction = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFutureAction.apply(scope, arguments);\n        };\n\n        return scope.dsl[key].apply(scope, arguments);\n      };\n    });\n    runner.run(spec, function() {\n      runner.$destroy();\n      specDone.apply(this, arguments);\n    });\n  },\n  function(error) {\n    if (error) {\n      self.emit('RunnerError', error);\n    }\n    self.emit('RunnerEnd');\n  });\n};\n\n/**\n * This class is the \"this\" of the it/beforeEach/afterEach method.\n * Responsibilities:\n *   - \"this\" for it/beforeEach/afterEach\n *   - keep state for single it/beforeEach/afterEach execution\n *   - keep track of all of the futures to execute\n *   - run single spec (execute each future)\n */\nangular.scenario.SpecRunner = function() {\n  this.futures = [];\n  this.afterIndex = 0;\n};\n\n/**\n * Executes a spec which is an it block with associated before/after functions\n * based on the describe nesting.\n *\n * @param {Object} spec A spec object\n * @param {function()} specDone function that is called when the spec finshes. Function(error, index)\n */\nangular.scenario.SpecRunner.prototype.run = function(spec, specDone) {\n  var self = this;\n  this.spec = spec;\n\n  this.emit('SpecBegin', spec);\n\n  try {\n    spec.before.call(this);\n    spec.body.call(this);\n    this.afterIndex = this.futures.length;\n    spec.after.call(this);\n  } catch (e) {\n    this.emit('SpecError', spec, e);\n    this.emit('SpecEnd', spec);\n    specDone();\n    return;\n  }\n\n  var handleError = function(error, done) {\n    if (self.error) {\n      return done();\n    }\n    self.error = true;\n    done(null, self.afterIndex);\n  };\n\n  asyncForEach(\n    this.futures,\n    function(future, futureDone) {\n      self.step = future;\n      self.emit('StepBegin', spec, future);\n      try {\n        future.execute(function(error) {\n          if (error) {\n            self.emit('StepFailure', spec, future, error);\n            self.emit('StepEnd', spec, future);\n            return handleError(error, futureDone);\n          }\n          self.emit('StepEnd', spec, future);\n          self.$window.setTimeout(function() { futureDone(); }, 0);\n        });\n      } catch (e) {\n        self.emit('StepError', spec, future, e);\n        self.emit('StepEnd', spec, future);\n        handleError(e, futureDone);\n      }\n    },\n    function(e) {\n      if (e) {\n        self.emit('SpecError', spec, e);\n      }\n      self.emit('SpecEnd', spec);\n      // Call done in a timeout so exceptions don't recursively\n      // call this function\n      self.$window.setTimeout(function() { specDone(); }, 0);\n    }\n  );\n};\n\n/**\n * Adds a new future action.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFuture = function(name, behavior, line) {\n  var future = new angular.scenario.Future(name, angular.bind(this, behavior), line);\n  this.futures.push(future);\n  return future;\n};\n\n/**\n * Adds a new future action to be executed on the application window.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior, line) {\n  var self = this;\n  var NG = /\\[ng\\\\\\:/;\n  return this.addFuture(name, function(done) {\n    this.application.executeAction(function($window, $document) {\n\n      //TODO(esprehn): Refactor this so it doesn't need to be in here.\n      $document.elements = function(selector) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        selector = (self.selector || '') + ' ' + (selector || '');\n        selector = _jQuery.trim(selector) || '*';\n        angular.forEach(args, function(value, index) {\n          selector = selector.replace('$' + (index + 1), value);\n        });\n        var result = $document.find(selector);\n        if (selector.match(NG)) {\n          angular.forEach(['[ng-','[data-ng-','[x-ng-'], function(value, index){\n            result = result.add(selector.replace(NG, value), $document);\n          });\n        }\n        if (!result.length) {\n          throw {\n            type: 'selector',\n            message: 'Selector ' + selector + ' did not match any elements.'\n          };\n        }\n\n        return result;\n      };\n\n      try {\n        behavior.call(self, $window, $document, done);\n      } catch(e) {\n        if (e.type && e.type === 'selector') {\n          done(e.message);\n        } else {\n          throw e;\n        }\n      }\n    });\n  }, line);\n};\n\n/**\n * Shared DSL statements that are useful to all scenarios.\n */\n\n /**\n * Usage:\n *    pause() pauses until you call resume() in the console\n */\nangular.scenario.dsl('pause', function() {\n  return function() {\n    return this.addFuture('pausing for you to resume', function(done) {\n      this.emit('InteractivePause', this.spec, this.step);\n      this.$window.resume = function() { done(); };\n    });\n  };\n});\n\n/**\n * Usage:\n *    sleep(seconds) pauses the test for specified number of seconds\n */\nangular.scenario.dsl('sleep', function() {\n  return function(time) {\n    return this.addFuture('sleep for ' + time + ' seconds', function(done) {\n      this.$window.setTimeout(function() { done(null, time * 1000); }, time * 1000);\n    });\n  };\n});\n\n/**\n * Usage:\n *    browser().navigateTo(url) Loads the url into the frame\n *    browser().navigateTo(url, fn) where fn(url) is called and returns the URL to navigate to\n *    browser().reload() refresh the page (reload the same URL)\n *    browser().window.href() window.location.href\n *    browser().window.path() window.location.pathname\n *    browser().window.search() window.location.search\n *    browser().window.hash() window.location.hash without # prefix\n *    browser().location().url() see ng.$location#url\n *    browser().location().path() see ng.$location#path\n *    browser().location().search() see ng.$location#search\n *    browser().location().hash() see ng.$location#hash\n */\nangular.scenario.dsl('browser', function() {\n  var chain = {};\n\n  chain.navigateTo = function(url, delegate) {\n    var application = this.application;\n    return this.addFuture(\"browser navigate to '\" + url + \"'\", function(done) {\n      if (delegate) {\n        url = delegate.call(this, url);\n      }\n      application.navigateTo(url, function() {\n        done(null, url);\n      }, done);\n    });\n  };\n\n  chain.reload = function() {\n    var application = this.application;\n    return this.addFutureAction('browser reload', function($window, $document, done) {\n      var href = $window.location.href;\n      application.navigateTo(href, function() {\n        done(null, href);\n      }, done);\n    });\n  };\n\n  chain.window = function() {\n    var api = {};\n\n    api.href = function() {\n      return this.addFutureAction('window.location.href', function($window, $document, done) {\n        done(null, $window.location.href);\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('window.location.path', function($window, $document, done) {\n        done(null, $window.location.pathname);\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('window.location.search', function($window, $document, done) {\n        done(null, $window.location.search);\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('window.location.hash', function($window, $document, done) {\n        done(null, $window.location.hash.replace('#', ''));\n      });\n    };\n\n    return api;\n  };\n\n  chain.location = function() {\n    var api = {};\n\n    api.url = function() {\n      return this.addFutureAction('$location.url()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').url());\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('$location.path()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').path());\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('$location.search()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').search());\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('$location.hash()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').hash());\n      });\n    };\n\n    return api;\n  };\n\n  return function() {\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    expect(future).{matcher} where matcher is one of the matchers defined\n *    with angular.scenario.matcher\n *\n * ex. expect(binding(\"name\")).toEqual(\"Elliott\")\n */\nangular.scenario.dsl('expect', function() {\n  var chain = angular.extend({}, angular.scenario.matcher);\n\n  chain.not = function() {\n    this.inverse = true;\n    return chain;\n  };\n\n  return function(future) {\n    this.future = future;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    using(selector, label) scopes the next DSL element selection\n *\n * ex.\n *   using('#foo', \"'Foo' text field\").input('bar')\n */\nangular.scenario.dsl('using', function() {\n  return function(selector, label) {\n    this.selector = _jQuery.trim((this.selector||'') + ' ' + selector);\n    if (angular.isString(label) && label.length) {\n      this.label = label + ' ( ' + this.selector + ' )';\n    } else {\n      this.label = this.selector;\n    }\n    return this.dsl;\n  };\n});\n\n/**\n * Usage:\n *    binding(name) returns the value of the first matching binding\n */\nangular.scenario.dsl('binding', function() {\n  return function(name) {\n    return this.addFutureAction(\"select binding '\" + name + \"'\", function($window, $document, done) {\n      var values = $document.elements().bindings($window.angular.element, name);\n      if (!values.length) {\n        return done(\"Binding selector '\" + name + \"' did not match.\");\n      }\n      done(null, values[0]);\n    });\n  };\n});\n\n/**\n * Usage:\n *    input(name).enter(value) enters value in input with specified name\n *    input(name).check() checks checkbox\n *    input(name).select(value) selects the radio button with specified name/value\n *    input(name).val() returns the value of the input.\n */\nangular.scenario.dsl('input', function() {\n  var chain = {};\n  var supportInputEvent =  'oninput' in document.createElement('div') && msie != 9;\n\n  chain.enter = function(value, event) {\n    return this.addFutureAction(\"input '\" + this.name + \"' enter '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      input.val(value);\n      input.trigger(event || (supportInputEvent ? 'input' : 'change'));\n      done();\n    });\n  };\n\n  chain.check = function() {\n    return this.addFutureAction(\"checkbox '\" + this.name + \"' toggle\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':checkbox');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.select = function(value) {\n    return this.addFutureAction(\"radio button '\" + this.name + \"' toggle '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.\n        elements('[ng\\\\:model=\"$1\"][value=\"$2\"]', this.name, value).filter(':radio');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.val = function() {\n    return this.addFutureAction(\"return input val\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      done(null,input.val());\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n\n/**\n * Usage:\n *    repeater('#products table', 'Product List').count() number of rows\n *    repeater('#products table', 'Product List').row(1) all bindings in row as an array\n *    repeater('#products table', 'Product List').column('product.name') all values across all rows in an array\n */\nangular.scenario.dsl('repeater', function() {\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.column = function(binding) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' column '\" + binding + \"'\", function($window, $document, done) {\n      done(null, $document.elements().bindings($window.angular.element, binding));\n    });\n  };\n\n  chain.row = function(index) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' row '\" + index + \"'\", function($window, $document, done) {\n      var matches = $document.elements().slice(index, index + 1);\n      if (!matches.length)\n        return done('row ' + index + ' out of bounds');\n      done(null, matches.bindings($window.angular.element));\n    });\n  };\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    select(name).option('value') select one option\n *    select(name).options('value1', 'value2', ...) select options from a multi select\n */\nangular.scenario.dsl('select', function() {\n  var chain = {};\n\n  chain.option = function(value) {\n    return this.addFutureAction(\"select '\" + this.name + \"' option '\" + value + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[ng\\\\:model=\"$1\"]', this.name);\n      var option = select.find('option[value=\"' + value + '\"]');\n      if (option.length) {\n        select.val(value);\n      } else {\n        option = select.find('option:contains(\"' + value + '\")');\n        if (option.length) {\n          select.val(option.val());\n        }\n      }\n      select.trigger('change');\n      done();\n    });\n  };\n\n  chain.options = function() {\n    var values = arguments;\n    return this.addFutureAction(\"select '\" + this.name + \"' options '\" + values + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[multiple][ng\\\\:model=\"$1\"]', this.name);\n      select.val(values);\n      select.trigger('change');\n      done();\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    element(selector, label).count() get the number of elements that match selector\n *    element(selector, label).click() clicks an element\n *    element(selector, label).query(fn) executes fn(selectedElements, done)\n *    element(selector, label).{method}() gets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(value) sets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(key) gets the value (as defined by jQuery, ex. attr)\n *    element(selector, label).{method}(key, value) sets the value (as defined by jQuery, ex. attr)\n */\nangular.scenario.dsl('element', function() {\n  var KEY_VALUE_METHODS = ['attr', 'css', 'prop'];\n  var VALUE_METHODS = [\n    'val', 'text', 'html', 'height', 'innerHeight', 'outerHeight', 'width',\n    'innerWidth', 'outerWidth', 'position', 'scrollLeft', 'scrollTop', 'offset'\n  ];\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.click = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' click\", function($window, $document, done) {\n      var elements = $document.elements();\n      var href = elements.attr('href');\n      var eventProcessDefault = elements.trigger('click')[0];\n\n      if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {\n        this.application.navigateTo(href, function() {\n          done();\n        }, done);\n      } else {\n        done();\n      }\n    });\n  };\n\n  chain.query = function(fn) {\n    return this.addFutureAction('element ' + this.label + ' custom query', function($window, $document, done) {\n      fn.call(this, $document.elements(), done);\n    });\n  };\n\n  angular.forEach(KEY_VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(name, value) {\n      var args = arguments,\n          futureName = (args.length == 1)\n              ? \"element '\" + this.label + \"' get \" + methodName + \" '\" + name + \"'\"\n              : \"element '\" + this.label + \"' set \" + methodName + \" '\" + name + \"' to \" + \"'\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  angular.forEach(VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(value) {\n      var args = arguments,\n          futureName = (args.length == 0)\n              ? \"element '\" + this.label + \"' \" + methodName\n              : futureName = \"element '\" + this.label + \"' set \" + methodName + \" to '\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Matchers for implementing specs. Follows the Jasmine spec conventions.\n */\n\nangular.scenario.matcher('toEqual', function(expected) {\n  return angular.equals(this.actual, expected);\n});\n\nangular.scenario.matcher('toBe', function(expected) {\n  return this.actual === expected;\n});\n\nangular.scenario.matcher('toBeDefined', function() {\n  return angular.isDefined(this.actual);\n});\n\nangular.scenario.matcher('toBeTruthy', function() {\n  return this.actual;\n});\n\nangular.scenario.matcher('toBeFalsy', function() {\n  return !this.actual;\n});\n\nangular.scenario.matcher('toMatch', function(expected) {\n  return new RegExp(expected).test(this.actual);\n});\n\nangular.scenario.matcher('toBeNull', function() {\n  return this.actual === null;\n});\n\nangular.scenario.matcher('toContain', function(expected) {\n  return includes(this.actual, expected);\n});\n\nangular.scenario.matcher('toBeLessThan', function(expected) {\n  return this.actual < expected;\n});\n\nangular.scenario.matcher('toBeGreaterThan', function(expected) {\n  return this.actual > expected;\n});\n\n/**\n * User Interface for the Scenario Runner.\n *\n * TODO(esprehn): This should be refactored now that ObjectModel exists\n *  to use angular bindings for the UI.\n */\nangular.scenario.output('html', function(context, runner, model) {\n  var specUiMap = {},\n      lastStepUiMap = {};\n\n  context.append(\n    '<div id=\"header\">' +\n    '  <h1><span class=\"angular\">AngularJS</span>: Scenario Test Runner</h1>' +\n    '  <ul id=\"status-legend\" class=\"status-display\">' +\n    '    <li class=\"status-error\">0 Errors</li>' +\n    '    <li class=\"status-failure\">0 Failures</li>' +\n    '    <li class=\"status-success\">0 Passed</li>' +\n    '  </ul>' +\n    '</div>' +\n    '<div id=\"specs\">' +\n    '  <div class=\"test-children\"></div>' +\n    '</div>'\n  );\n\n  runner.on('InteractivePause', function(spec) {\n    var ui = lastStepUiMap[spec.id];\n    ui.find('.test-title').\n      html('paused... <a href=\"javascript:resume()\">resume</a> when ready.');\n  });\n\n  runner.on('SpecBegin', function(spec) {\n    var ui = findContext(spec);\n    ui.find('> .tests').append(\n      '<li class=\"status-pending test-it\"></li>'\n    );\n    ui = ui.find('> .tests li:last');\n    ui.append(\n      '<div class=\"test-info\">' +\n      '  <p class=\"test-title\">' +\n      '    <span class=\"timer-result\"></span>' +\n      '    <span class=\"test-name\"></span>' +\n      '  </p>' +\n      '</div>' +\n      '<div class=\"scrollpane\">' +\n      '  <ol class=\"test-actions\"></ol>' +\n      '</div>'\n    );\n    ui.find('> .test-info .test-name').text(spec.name);\n    ui.find('> .test-info').click(function() {\n      var scrollpane = ui.find('> .scrollpane');\n      var actions = scrollpane.find('> .test-actions');\n      var name = context.find('> .test-info .test-name');\n      if (actions.find(':visible').length) {\n        actions.hide();\n        name.removeClass('open').addClass('closed');\n      } else {\n        actions.show();\n        scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n        name.removeClass('closed').addClass('open');\n      }\n    });\n\n    specUiMap[spec.id] = ui;\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var ui = specUiMap[spec.id];\n    ui.append('<pre></pre>');\n    ui.find('> pre').text(formatException(error));\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    ui.removeClass('status-pending');\n    ui.addClass('status-' + spec.status);\n    ui.find(\"> .test-info .timer-result\").text(spec.duration + \"ms\");\n    if (spec.status === 'success') {\n      ui.find('> .test-info .test-name').addClass('closed');\n      ui.find('> .scrollpane .test-actions').hide();\n    }\n    updateTotals(spec.status);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    ui.find('> .scrollpane .test-actions').append('<li class=\"status-pending\"></li>');\n    var stepUi = lastStepUiMap[spec.id] = ui.find('> .scrollpane .test-actions li:last');\n    stepUi.append(\n      '<div class=\"timer-result\"></div>' +\n      '<div class=\"test-title\"></div>'\n    );\n    stepUi.find('> .test-title').text(step.name);\n    var scrollpane = stepUi.parents('.scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepEnd', function(spec, step) {\n    var stepUi = lastStepUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    stepUi.find('.timer-result').text(step.duration + 'ms');\n    stepUi.removeClass('status-pending');\n    stepUi.addClass('status-' + step.status);\n    var scrollpane = specUiMap[spec.id].find('> .scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  /**\n   * Finds the context of a spec block defined by the passed definition.\n   *\n   * @param {Object} The definition created by the Describe object.\n   */\n  function findContext(spec) {\n    var currentContext = context.find('#specs');\n    angular.forEach(model.getDefinitionPath(spec), function(defn) {\n      var id = 'describe-' + defn.id;\n      if (!context.find('#' + id).length) {\n        currentContext.find('> .test-children').append(\n          '<div class=\"test-describe\" id=\"' + id + '\">' +\n          '  <h2></h2>' +\n          '  <div class=\"test-children\"></div>' +\n          '  <ul class=\"tests\"></ul>' +\n          '</div>'\n        );\n        context.find('#' + id).find('> h2').text('describe: ' + defn.name);\n      }\n      currentContext = context.find('#' + id);\n    });\n    return context.find('#describe-' + spec.definition.id);\n  }\n\n  /**\n   * Updates the test counter for the status.\n   *\n   * @param {string} the status.\n   */\n  function updateTotals(status) {\n    var legend = context.find('#status-legend .status-' + status);\n    var parts = legend.text().split(' ');\n    var value = (parts[0] * 1) + 1;\n    legend.text(value + ' ' + parts[1]);\n  }\n\n  /**\n   * Add an error to a step.\n   *\n   * @param {Object} The JQuery wrapped context\n   * @param {function()} fn() that should return the file/line number of the error\n   * @param {Object} the error.\n   */\n  function addError(context, line, error) {\n    context.find('.test-title').append('<pre></pre>');\n    var message = _jQuery.trim(line() + '\\n\\n' + formatException(error));\n    context.find('.test-title pre:last').text(message);\n  }\n});\n\n/**\n * Generates JSON output into a context.\n */\nangular.scenario.output('json', function(context, runner, model) {\n  model.on('RunnerEnd', function() {\n    context.text(angular.toJson(model.value));\n  });\n});\n\n/**\n * Generates XML output into a context.\n */\nangular.scenario.output('xml', function(context, runner, model) {\n  var $ = function(args) {return new context.init(args);};\n  model.on('RunnerEnd', function() {\n    var scenario = $('<scenario></scenario>');\n    context.append(scenario);\n    serializeXml(scenario, model.value);\n  });\n\n  /**\n   * Convert the tree into XML.\n   *\n   * @param {Object} context jQuery context to add the XML to.\n   * @param {Object} tree node to serialize\n   */\n  function serializeXml(context, tree) {\n     angular.forEach(tree.children, function(child) {\n       var describeContext = $('<describe></describe>');\n       describeContext.attr('id', child.id);\n       describeContext.attr('name', child.name);\n       context.append(describeContext);\n       serializeXml(describeContext, child);\n     });\n     var its = $('<its></its>');\n     context.append(its);\n     angular.forEach(tree.specs, function(spec) {\n       var it = $('<it></it>');\n       it.attr('id', spec.id);\n       it.attr('name', spec.name);\n       it.attr('duration', spec.duration);\n       it.attr('status', spec.status);\n       its.append(it);\n       angular.forEach(spec.steps, function(step) {\n         var stepContext = $('<step></step>');\n         stepContext.attr('name', step.name);\n         stepContext.attr('duration', step.duration);\n         stepContext.attr('status', step.status);\n         it.append(stepContext);\n         if (step.error) {\n           var error = $('<error></error>');\n           stepContext.append(error);\n           error.text(formatException(stepContext.error));\n         }\n       });\n     });\n   }\n});\n\n/**\n * Creates a global value $result with the result of the runner.\n */\nangular.scenario.output('object', function(context, runner, model) {\n  runner.$window.$result = model.value;\n});\nbindJQuery();\npublishExternalAPI(angular);\n\nvar $runner = new angular.scenario.Runner(window),\n    scripts = document.getElementsByTagName('script'),\n    script = scripts[scripts.length - 1],\n    config = {};\n\nangular.forEach(script.attributes, function(attr) {\n  var match = attr.name.match(/ng[:\\-](.*)/);\n  if (match) {\n    config[match[1]] = attr.value || true;\n  }\n});\n\nif (config.autotest) {\n  JQLite(document).ready(function() {\n    angular.scenario.setUpAndRun(config);\n  });\n}\n})(window, document);\n\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n\\n[ng\\\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\\n.ng-cloak, .x-ng-cloak {\\n  display: none;\\n}\\n\\nng\\\\:form {\\n  display: block;\\n}\\n</style>');\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n/* CSS Document */\\n\\n/** Structure */\\nbody {\\n  font-family: Arial, sans-serif;\\n  margin: 0;\\n  font-size: 14px;\\n}\\n\\n#system-error {\\n  font-size: 1.5em;\\n  text-align: center;\\n}\\n\\n#json, #xml {\\n  display: none;\\n}\\n\\n#header {\\n  position: fixed;\\n  width: 100%;\\n}\\n\\n#specs {\\n  padding-top: 50px;\\n}\\n\\n#header .angular {\\n  font-family: Courier New, monospace;\\n  font-weight: bold;\\n}\\n\\n#header h1 {\\n  font-weight: normal;\\n  float: left;\\n  font-size: 30px;\\n  line-height: 30px;\\n  margin: 0;\\n  padding: 10px 10px;\\n  height: 30px;\\n}\\n\\n#application h2,\\n#specs h2 {\\n  margin: 0;\\n  padding: 0.5em;\\n  font-size: 1.1em;\\n}\\n\\n#status-legend {\\n  margin-top: 10px;\\n  margin-right: 10px;\\n}\\n\\n#header,\\n#application,\\n.test-info,\\n.test-actions li {\\n  overflow: hidden;\\n}\\n\\n#application {\\n  margin: 10px;\\n}\\n\\n#application iframe {\\n  width: 100%;\\n  height: 758px;\\n}\\n\\n#application .popout {\\n  float: right;\\n}\\n\\n#application iframe {\\n  border: none;\\n}\\n\\n.tests li,\\n.test-actions li,\\n.test-it li,\\n.test-it ol,\\n.status-display {\\n  list-style-type: none;\\n}\\n\\n.tests,\\n.test-it ol,\\n.status-display {\\n  margin: 0;\\n  padding: 0;\\n}\\n\\n.test-info {\\n  margin-left: 1em;\\n  margin-top: 0.5em;\\n  border-radius: 8px 0 0 8px;\\n  -webkit-border-radius: 8px 0 0 8px;\\n  -moz-border-radius: 8px 0 0 8px;\\n  cursor: pointer;\\n}\\n\\n.test-info:hover .test-name {\\n  text-decoration: underline;\\n}\\n\\n.test-info .closed:before {\\n  content: \\'\\\\25b8\\\\00A0\\';\\n}\\n\\n.test-info .open:before {\\n  content: \\'\\\\25be\\\\00A0\\';\\n  font-weight: bold;\\n}\\n\\n.test-it ol {\\n  margin-left: 2.5em;\\n}\\n\\n.status-display,\\n.status-display li {\\n  float: right;\\n}\\n\\n.status-display li {\\n  padding: 5px 10px;\\n}\\n\\n.timer-result,\\n.test-title {\\n  display: inline-block;\\n  margin: 0;\\n  padding: 4px;\\n}\\n\\n.test-actions .test-title,\\n.test-actions .test-result {\\n  display: table-cell;\\n  padding-left: 0.5em;\\n  padding-right: 0.5em;\\n}\\n\\n.test-actions {\\n  display: table;\\n}\\n\\n.test-actions li {\\n  display: table-row;\\n}\\n\\n.timer-result {\\n  width: 4em;\\n  padding: 0 10px;\\n  text-align: right;\\n  font-family: monospace;\\n}\\n\\n.test-it pre,\\n.test-actions pre {\\n  clear: left;\\n  color: black;\\n  margin-left: 6em;\\n}\\n\\n.test-describe {\\n  padding-bottom: 0.5em;\\n}\\n\\n.test-describe .test-describe {\\n  margin: 5px 5px 10px 2em;\\n}\\n\\n.test-actions .status-pending .test-title:before {\\n  content: \\'\\\\00bb\\\\00A0\\';\\n}\\n\\n.scrollpane {\\n   max-height: 20em;\\n   overflow: auto;\\n}\\n\\n/** Colors */\\n\\n#header {\\n  background-color: #F2C200;\\n}\\n\\n#specs h2 {\\n  border-top: 2px solid #BABAD1;\\n}\\n\\n#specs h2,\\n#application h2 {\\n  background-color: #efefef;\\n}\\n\\n#application {\\n  border: 1px solid #BABAD1;\\n}\\n\\n.test-describe .test-describe {\\n  border-left: 1px solid #BABAD1;\\n  border-right: 1px solid #BABAD1;\\n  border-bottom: 1px solid #BABAD1;\\n}\\n\\n.status-display {\\n  border: 1px solid #777;\\n}\\n\\n.status-display .status-pending,\\n.status-pending .test-info {\\n  background-color: #F9EEBC;\\n}\\n\\n.status-display .status-success,\\n.status-success .test-info {\\n  background-color: #B1D7A1;\\n}\\n\\n.status-display .status-failure,\\n.status-failure .test-info {\\n  background-color: #FF8286;\\n}\\n\\n.status-display .status-error,\\n.status-error .test-info {\\n  background-color: black;\\n  color: white;\\n}\\n\\n.test-actions .status-success .test-title {\\n  color: #30B30A;\\n}\\n\\n.test-actions .status-failure .test-title {\\n  color: #DF0000;\\n}\\n\\n.test-actions .status-error .test-title {\\n  color: black;\\n}\\n\\n.test-actions .timer-result {\\n  color: #888;\\n}\\n</style>');"
  },
  {
    "path": "chapter4/recipe4/test/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter4/recipe4/test/lib/jasmine-jquery.js",
    "content": "var readFixtures = function() {\n  return jasmine.getFixtures().proxyCallTo_('read', arguments)\n}\n\nvar preloadFixtures = function() {\n  jasmine.getFixtures().proxyCallTo_('preload', arguments)\n}\n\nvar loadFixtures = function() {\n  jasmine.getFixtures().proxyCallTo_('load', arguments)\n}\n\nvar appendLoadFixtures = function() {\n  jasmine.getFixtures().proxyCallTo_('appendLoad', arguments)\n}\n\nvar setFixtures = function(html) {\n  jasmine.getFixtures().proxyCallTo_('set', arguments)\n}\n\nvar appendSetFixtures = function() {\n  jasmine.getFixtures().proxyCallTo_('appendSet', arguments)\n}\n\nvar sandbox = function(attributes) {\n  return jasmine.getFixtures().sandbox(attributes)\n}\n\nvar spyOnEvent = function(selector, eventName) {\n  return jasmine.JQuery.events.spyOn(selector, eventName)\n}\n\nvar preloadStyleFixtures = function() {\n  jasmine.getStyleFixtures().proxyCallTo_('preload', arguments)\n}\n\nvar loadStyleFixtures = function() {\n  jasmine.getStyleFixtures().proxyCallTo_('load', arguments)\n}\n\nvar appendLoadStyleFixtures = function() {\n  jasmine.getStyleFixtures().proxyCallTo_('appendLoad', arguments)\n}\n\nvar setStyleFixtures = function(html) {\n  jasmine.getStyleFixtures().proxyCallTo_('set', arguments)\n}\n\nvar appendSetStyleFixtures = function(html) {\n  jasmine.getStyleFixtures().proxyCallTo_('appendSet', arguments)\n}\n\nvar loadJSONFixtures = function() {\n  return jasmine.getJSONFixtures().proxyCallTo_('load', arguments)\n}\n\nvar getJSONFixture = function(url) {\n  return jasmine.getJSONFixtures().proxyCallTo_('read', arguments)[url]\n}\n\njasmine.spiedEventsKey = function (selector, eventName) {\n  return [$(selector).selector, eventName].toString()\n}\n\njasmine.getFixtures = function() {\n  return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures()\n}\n\njasmine.getStyleFixtures = function() {\n  return jasmine.currentStyleFixtures_ = jasmine.currentStyleFixtures_ || new jasmine.StyleFixtures()\n}\n\njasmine.Fixtures = function() {\n  this.containerId = 'jasmine-fixtures'\n  this.fixturesCache_ = {}\n  this.fixturesPath = 'spec/javascripts/fixtures'\n}\n\njasmine.Fixtures.prototype.set = function(html) {\n  this.cleanUp()\n  this.createContainer_(html)\n}\n\njasmine.Fixtures.prototype.appendSet= function(html) {\n  this.addToContainer_(html)\n}\n\njasmine.Fixtures.prototype.preload = function() {\n  this.read.apply(this, arguments)\n}\n\njasmine.Fixtures.prototype.load = function() {\n  this.cleanUp()\n  this.createContainer_(this.read.apply(this, arguments))\n}\n\njasmine.Fixtures.prototype.appendLoad = function() {\n  this.addToContainer_(this.read.apply(this, arguments))\n}\n\njasmine.Fixtures.prototype.read = function() {\n  var htmlChunks = []\n\n  var fixtureUrls = arguments\n  for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {\n    htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex]))\n  }\n\n  return htmlChunks.join('')\n}\n\njasmine.Fixtures.prototype.clearCache = function() {\n  this.fixturesCache_ = {}\n}\n\njasmine.Fixtures.prototype.cleanUp = function() {\n  $('#' + this.containerId).remove()\n}\n\njasmine.Fixtures.prototype.sandbox = function(attributes) {\n  var attributesToSet = attributes || {}\n  return $('<div id=\"sandbox\" />').attr(attributesToSet)\n}\n\njasmine.Fixtures.prototype.createContainer_ = function(html) {\n  var container\n  if(html instanceof $) {\n    container = $('<div id=\"' + this.containerId + '\" />')\n    container.html(html)\n  } else {\n    container = '<div id=\"' + this.containerId + '\">' + html + '</div>'\n  }\n  $(document.body).append(container)\n}\n\njasmine.Fixtures.prototype.addToContainer_ = function(html){\n  var container = $(document.body).find('#'+this.containerId).append(html)\n  if(!container.length){\n    this.createContainer_(html)\n  }\n}\n\njasmine.Fixtures.prototype.getFixtureHtml_ = function(url) {\n  if (typeof this.fixturesCache_[url] === 'undefined') {\n    this.loadFixtureIntoCache_(url)\n  }\n  return this.fixturesCache_[url]\n}\n\njasmine.Fixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) {\n  var url = this.makeFixtureUrl_(relativeUrl)\n  var request = $.ajax({\n    type: \"GET\",\n    url: url + \"?\" + new Date().getTime(),\n    async: false\n  })\n  this.fixturesCache_[relativeUrl] = request.responseText\n}\n\njasmine.Fixtures.prototype.makeFixtureUrl_ = function(relativeUrl){\n  return this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl\n}\n\njasmine.Fixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) {\n  return this[methodName].apply(this, passedArguments)\n}\n\n\njasmine.StyleFixtures = function() {\n  this.fixturesCache_ = {}\n  this.fixturesNodes_ = []\n  this.fixturesPath = 'spec/javascripts/fixtures'\n}\n\njasmine.StyleFixtures.prototype.set = function(css) {\n  this.cleanUp()\n  this.createStyle_(css)\n}\n\njasmine.StyleFixtures.prototype.appendSet = function(css) {\n  this.createStyle_(css)\n}\n\njasmine.StyleFixtures.prototype.preload = function() {\n  this.read_.apply(this, arguments)\n}\n\njasmine.StyleFixtures.prototype.load = function() {\n  this.cleanUp()\n  this.createStyle_(this.read_.apply(this, arguments))\n}\n\njasmine.StyleFixtures.prototype.appendLoad = function() {\n  this.createStyle_(this.read_.apply(this, arguments))\n}\n\njasmine.StyleFixtures.prototype.cleanUp = function() {\n  while(this.fixturesNodes_.length) {\n    this.fixturesNodes_.pop().remove()\n  }\n}\n\njasmine.StyleFixtures.prototype.createStyle_ = function(html) {\n  var styleText = $('<div></div>').html(html).text(),\n    style = $('<style>' + styleText + '</style>')\n\n  this.fixturesNodes_.push(style)\n\n  $('head').append(style)\n}\n\njasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache\n\njasmine.StyleFixtures.prototype.read_ = jasmine.Fixtures.prototype.read\n\njasmine.StyleFixtures.prototype.getFixtureHtml_ = jasmine.Fixtures.prototype.getFixtureHtml_\n\njasmine.StyleFixtures.prototype.loadFixtureIntoCache_ = jasmine.Fixtures.prototype.loadFixtureIntoCache_\n\njasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.makeFixtureUrl_\n\njasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_\n\njasmine.getJSONFixtures = function() {\n  return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures()\n}\n\njasmine.JSONFixtures = function() {\n  this.fixturesCache_ = {}\n  this.fixturesPath = 'spec/javascripts/fixtures/json'\n}\n\njasmine.JSONFixtures.prototype.load = function() {\n  this.read.apply(this, arguments)\n  return this.fixturesCache_\n}\n\njasmine.JSONFixtures.prototype.read = function() {\n  var fixtureUrls = arguments\n  for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {\n    this.getFixtureData_(fixtureUrls[urlIndex])\n  }\n  return this.fixturesCache_\n}\n\njasmine.JSONFixtures.prototype.clearCache = function() {\n  this.fixturesCache_ = {}\n}\n\njasmine.JSONFixtures.prototype.getFixtureData_ = function(url) {\n  this.loadFixtureIntoCache_(url)\n  return this.fixturesCache_[url]\n}\n\njasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) {\n  var self = this\n  var url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl\n  $.ajax({\n    async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded\n    cache: false,\n    dataType: 'json',\n    url: url,\n    success: function(data) {\n      self.fixturesCache_[relativeUrl] = data\n    },\n    fail: function(jqXHR, status, errorThrown) {\n        throw Error('JSONFixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + errorThrown.message + ')')\n    }\n  })\n}\n\njasmine.JSONFixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) {\n  return this[methodName].apply(this, passedArguments)\n}\n\njasmine.JQuery = function() {}\n\njasmine.JQuery.browserTagCaseIndependentHtml = function(html) {\n  return $('<div/>').append(html).html()\n}\n\njasmine.JQuery.elementToString = function(element) {\n  var domEl = $(element).get(0)\n  if (domEl == undefined || domEl.cloneNode)\n    return $('<div />').append($(element).clone()).html()\n  else\n    return element.toString()\n}\n\njasmine.JQuery.matchersClass = {}\n\n!function(namespace) {\n  var data = {\n    spiedEvents: {},\n    handlers:    []\n  }\n\n  namespace.events = {\n    spyOn: function(selector, eventName) {\n      var handler = function(e) {\n        data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = e\n      }\n      $(selector).bind(eventName, handler)\n      data.handlers.push(handler)\n      return {\n        selector: selector,\n        eventName: eventName,\n        handler: handler,\n        reset: function(){\n          delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]\n        }\n      }\n    },\n\n    wasTriggered: function(selector, eventName) {\n      return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)])\n    },\n\n    wasPrevented: function(selector, eventName) {\n      var e;\n      return (e = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]) && e.isDefaultPrevented()\n    },\n\n    cleanUp: function() {\n      data.spiedEvents = {}\n      data.handlers    = []\n    }\n  }\n}(jasmine.JQuery)\n\n!function(){\n  var jQueryMatchers = {\n    toHaveClass: function(className) {\n      return this.actual.hasClass(className)\n    },\n\n    toHaveCss: function(css){\n      for (var prop in css){\n        if (this.actual.css(prop) !== css[prop]) return false\n      }\n      return true\n    },\n\n    toBeVisible: function() {\n      return this.actual.is(':visible')\n    },\n\n    toBeHidden: function() {\n      return this.actual.is(':hidden')\n    },\n\n    toBeSelected: function() {\n      return this.actual.is(':selected')\n    },\n\n    toBeChecked: function() {\n      return this.actual.is(':checked')\n    },\n\n    toBeEmpty: function() {\n      return this.actual.is(':empty')\n    },\n\n    toExist: function() {\n      return $(document).find(this.actual).length\n    },\n\n    toHaveLength: function(length) {\n      return this.actual.length === length\n    },\n\n    toHaveAttr: function(attributeName, expectedAttributeValue) {\n      return hasProperty(this.actual.attr(attributeName), expectedAttributeValue)\n    },\n\n    toHaveProp: function(propertyName, expectedPropertyValue) {\n      return hasProperty(this.actual.prop(propertyName), expectedPropertyValue)\n    },\n\n    toHaveId: function(id) {\n      return this.actual.attr('id') == id\n    },\n\n    toHaveHtml: function(html) {\n      return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html)\n    },\n\n    toContainHtml: function(html){\n      var actualHtml = this.actual.html()\n      var expectedHtml = jasmine.JQuery.browserTagCaseIndependentHtml(html)\n      return (actualHtml.indexOf(expectedHtml) >= 0)\n    },\n\n    toHaveText: function(text) {\n      var trimmedText = $.trim(this.actual.text())\n      if (text && $.isFunction(text.test)) {\n        return text.test(trimmedText)\n      } else {\n        return trimmedText == text\n      }\n    },\n\n    toHaveValue: function(value) {\n      return this.actual.val() === value\n    },\n\n    toHaveData: function(key, expectedValue) {\n      return hasProperty(this.actual.data(key), expectedValue)\n    },\n\n    toBe: function(selector) {\n      return this.actual.is(selector)\n    },\n\n    toContain: function(selector) {\n      return this.actual.find(selector).length\n    },\n\n    toBeDisabled: function(selector){\n      return this.actual.is(':disabled')\n    },\n\n    toBeFocused: function(selector) {\n      return this.actual[0] === this.actual[0].ownerDocument.activeElement\n    },\n\n    toHandle: function(event) {\n\n      var events = $._data(this.actual.get(0), \"events\")\n\n      if(!events || !event || typeof event !== \"string\") {\n        return false\n      }\n\n      var namespaces = event.split(\".\")\n      var eventType = namespaces.shift()\n      var sortedNamespaces = namespaces.slice(0).sort()\n      var namespaceRegExp = new RegExp(\"(^|\\\\.)\" + sortedNamespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\")\n\n      if(events[eventType] && namespaces.length) {\n        for(var i = 0; i < events[eventType].length; i++) {\n          var namespace = events[eventType][i].namespace\n          if(namespaceRegExp.test(namespace)) {\n            return true\n          }\n        }\n      } else {\n        return events[eventType] && events[eventType].length > 0\n      }\n    },\n\n    // tests the existence of a specific event binding + handler\n    toHandleWith: function(eventName, eventHandler) {\n      var stack = $._data(this.actual.get(0), \"events\")[eventName]\n      for (var i = 0; i < stack.length; i++) {\n        if (stack[i].handler == eventHandler) return true\n      }\n      return false\n    }\n  }\n\n  var hasProperty = function(actualValue, expectedValue) {\n    if (expectedValue === undefined) return actualValue !== undefined\n    return actualValue == expectedValue\n  }\n\n  var bindMatcher = function(methodName) {\n    var builtInMatcher = jasmine.Matchers.prototype[methodName]\n\n    jasmine.JQuery.matchersClass[methodName] = function() {\n      if (this.actual\n        && (this.actual instanceof $\n          || jasmine.isDomNode(this.actual))) {\n            this.actual = $(this.actual)\n            var result = jQueryMatchers[methodName].apply(this, arguments)\n            var element\n            if (this.actual.get && (element = this.actual.get()[0]) && !$.isWindow(element) && element.tagName !== \"HTML\")\n              this.actual = jasmine.JQuery.elementToString(this.actual)\n            return result\n          }\n\n          if (builtInMatcher) {\n            return builtInMatcher.apply(this, arguments)\n          }\n\n          return false\n    }\n  }\n\n  for(var methodName in jQueryMatchers) {\n    bindMatcher(methodName)\n  }\n}()\n\nbeforeEach(function() {\n  this.addMatchers(jasmine.JQuery.matchersClass)\n  this.addMatchers({\n    toHaveBeenTriggeredOn: function(selector) {\n      this.message = function() {\n        return [\n          \"Expected event \" + this.actual + \" to have been triggered on \" + selector,\n          \"Expected event \" + this.actual + \" not to have been triggered on \" + selector\n        ]\n      }\n      return jasmine.JQuery.events.wasTriggered(selector, this.actual)\n    }\n  })\n  this.addMatchers({\n    toHaveBeenTriggered: function(){\n      var eventName = this.actual.eventName,\n          selector = this.actual.selector\n      this.message = function() {\n        return [\n          \"Expected event \" + eventName + \" to have been triggered on \" + selector,\n          \"Expected event \" + eventName + \" not to have been triggered on \" + selector\n        ]\n      }\n      return jasmine.JQuery.events.wasTriggered(selector, eventName)\n     }\n  })\n  this.addMatchers({\n    toHaveBeenPreventedOn: function(selector) {\n      this.message = function() {\n        return [\n          \"Expected event \" + this.actual + \" to have been prevented on \" + selector,\n          \"Expected event \" + this.actual + \" not to have been prevented on \" + selector\n        ]\n      }\n      return jasmine.JQuery.events.wasPrevented(selector, this.actual)\n    }\n  })\n  this.addMatchers({\n    toHaveBeenPrevented: function() {\n      var eventName = this.actual.eventName,\n          selector = this.actual.selector\n      this.message = function() {\n        return [\n          \"Expected event \" + eventName + \" to have been prevented on \" + selector,\n          \"Expected event \" + eventName + \" not to have been prevented on \" + selector\n        ]\n      }\n      return jasmine.JQuery.events.wasPrevented(selector, eventName)\n    }\n  })\n})\n\nafterEach(function() {\n  jasmine.getFixtures().cleanUp()\n  jasmine.getStyleFixtures().cleanUp()\n  jasmine.JQuery.events.cleanUp()\n})"
  },
  {
    "path": "chapter4/recipe4/test/unit/filtersSpec.js",
    "content": "describe('MyApp', function() {\n  beforeEach(module('MyApp'));\n\n  describe('checkmark', function() {\n     it('should convert boolean values to unicode checkmark or cross', inject(function(checkmarkFilter) {\n       expect(checkmarkFilter(true)).toBe('\\u2713');\n       expect(checkmarkFilter(false)).toBe('\\u2718');\n     }));\n   });\n});"
  },
  {
    "path": "chapter5/recipe1/README.md",
    "content": "# angular-seed — the seed for AngularJS apps\n\nThis project is an application skeleton for a typical [AngularJS](http://angularjs.org/) web app.\nYou can use it to quickly bootstrap your angular webapp projects and dev environment for these\nprojects.\n\nThe seed contains AngularJS libraries, test libraries and a bunch of scripts all preconfigured for\ninstant web development gratification. Just clone the repo (or download the zip/tarball), start up\nour (or yours) webserver and you are ready to develop and test your application.\n\nThe seed app doesn't do much, just shows how to wire two controllers and views together. You can\ncheck it out by opening app/index.html in your browser (might not work file `file://` scheme in\ncertain browsers, see note below).\n\n_Note: While angular is client-side-only technology and it's possible to create angular webapps that\ndon't require a backend server at all, we recommend hosting the project files using a local\nwebserver during development to avoid issues with security restrictions (sandbox) in browsers. The\nsandbox implementation varies between browsers, but quite often prevents things like cookies, xhr,\netc to function properly when an html page is opened via `file://` scheme instead of `http://`._\n\n\n## How to use angular-seed\n\nClone the angular-seed repository and start hacking...\n\n\n### Running the app during development\n\nYou can pick one of these options:\n\n* serve this repository with your webserver\n* install node.js and run `scripts/web-server.js`\n\nThen navigate your browser to `http://localhost:<port>/app/index.html` to see the app running in\nyour browser.\n\n\n### Running the app in production\n\nThis really depends on how complex is your app and the overall infrastructure of your system, but\nthe general rule is that all you need in production are all the files under the `app/` directory.\nEverything else should be omitted.\n\nAngular apps are really just a bunch of static html, css and js files that just need to be hosted\nsomewhere, where they can be accessed by browsers.\n\nIf your Angular app is talking to the backend server via xhr or other means, you need to figure\nout what is the best way to host the static files to comply with the same origin policy if\napplicable. Usually this is done by hosting the files by the backend server or through\nreverse-proxying the backend server(s) and a webserver(s).\n\n\n### Running unit tests\n\nWe recommend using [jasmine](http://pivotal.github.com/jasmine/) and\n[Testacular](http://vojtajina.github.com/testacular/) for your unit tests/specs, but you are free\nto use whatever works for you.\n\nRequires [node.js](http://nodejs.org/), Testacular (`sudo npm install -g testacular`) and a local\nor remote browser.\n\n* start `scripts/test.sh` (on windows: `scripts\\test.bat`)\n  * a browser will start and connect to the Testacular server (Chrome is default browser, others can be captured by loading the same url as the one in Chrome or by changing the `config/testacular.conf.js` file)\n* to run or re-run tests just change any of your source or test javascript files\n\n\n### End to end testing\n\nAngular ships with a baked-in end-to-end test runner that understands angular, your app and allows\nyou to write your tests with jasmine-like BDD syntax.\n\nRequires a webserver, node.js + `./scripts/web-server.js` or your backend server that hosts the angular static files.\n\nCheck out the\n[end-to-end runner's documentation](http://docs.angularjs.org/guide/dev_guide.e2e-testing) for more\ninfo.\n\n* create your end-to-end tests in `test/e2e/scenarios.js`\n* serve your project directory with your http/backend server or node.js + `scripts/web-server.js`\n* to run do one of:\n  * open `http://localhost:port/test/e2e/runner.html` in your browser\n  * run the tests from console with [Testacular](vojtajina.github.com/testacular) via\n    `scripts/e2e-test.sh` or `script/e2e-test.bat`\n\n\n### Receiving updates from upstream\n\nWhen we upgrade angular-seed's repo with newer angular or testing library code, you can just\nfetch the changes and merge them into your project with git.\n\n\n## Directory Layout\n\n    app/                --> all of the files to be used in production\n      css/              --> css files\n        app.css         --> default stylesheet\n      img/              --> image files\n      index.html        --> app layout file (the main html template file of the app)\n      index-async.html  --> just like index.html, but loads js files asynchronously\n      js/               --> javascript files\n        app.js          --> application\n        controllers.js  --> application controllers\n        directives.js   --> application directives\n        filters.js      --> custom angular filters\n        services.js     --> custom angular services\n      lib/              --> angular and 3rd party javascript libraries\n        angular/\n          angular.js        --> the latest angular js\n          angular.min.js    --> the latest minified angular js\n          angular-*.js      --> angular add-on modules\n          version.txt       --> version number\n      partials/             --> angular view partials (partial html templates)\n        partial1.html\n        partial2.html\n\n    config/testacular.conf.js        --> config file for running unit tests with Testacular\n    config/testacular-e2e.conf.js    --> config file for running e2e tests with Testacular\n\n    scripts/            --> handy shell/js/ruby scripts\n      e2e-test.sh       --> runs end-to-end tests with Testacular (*nix)\n      e2e-test.bat      --> runs end-to-end tests with Testacular (windows)\n      test.bat          --> autotests unit tests with Testacular (windows)\n      test.sh           --> autotests unit tests with Testacular (*nix)\n      web-server.js     --> simple development webserver based on node.js\n\n    test/               --> test source files and libraries\n      e2e/              -->\n        runner.html     --> end-to-end test runner (open in your browser to run)\n        scenarios.js    --> end-to-end specs\n      lib/\n        angular/                --> angular testing libraries\n          angular-mocks.js      --> mocks that replace certain angular services in tests\n          angular-scenario.js   --> angular's scenario (end-to-end) test runner library\n          version.txt           --> version file\n      unit/                     --> unit level specs/tests\n        controllersSpec.js      --> specs for controllers\n        directivessSpec.js      --> specs for directives\n        filtersSpec.js          --> specs for filters\n        servicesSpec.js         --> specs for services\n\n## Contact\n\nFor more information on AngularJS please check out http://angularjs.org/\n"
  },
  {
    "path": "chapter5/recipe1/app/css/.gitignore",
    "content": ""
  },
  {
    "path": "chapter5/recipe1/app/css/app.css",
    "content": "/* app css stylesheet */\n\n.menu {\n  list-style: none;\n  border-bottom: 0.1em solid black;\n  margin-bottom: 2em;\n  padding: 0 0 0.5em;\n}\n\n.menu:before {\n  content: \"[\";\n}\n\n.menu:after {\n  content: \"]\";\n}\n\n.menu > li {\n  display: inline;\n}\n\n.menu > li:before {\n  content: \"|\";\n  padding-right: 0.3em;\n}\n\n.menu > li:nth-child(1):before {\n  content: \"\";\n  padding: 0;\n}\n"
  },
  {
    "path": "chapter5/recipe1/app/data/posts.json",
    "content": "[\n  { \n    \"id\": 1,\n    \"title\": \"Lorem ipsum 1\"\n  },\n  { \n    \"id\": 2,\n    \"title\": \"Lorem ipsum 2\"\n  }\n]"
  },
  {
    "path": "chapter5/recipe1/app/img/.gitignore",
    "content": ""
  },
  {
    "path": "chapter5/recipe1/app/index-async.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <style>\n    [ng-cloak] {\n      display: none;\n    }\n  </style>\n  <script>\n    // include angular loader, which allows the files to load in any order\n    /*\n     AngularJS v1.0.0rc1\n     (c) 2010-2012 AngularJS http://angularjs.org\n     License: MIT\n    */\n    'use strict';(function(i){function d(c,a,e){return c[a]||(c[a]=e())}return d(d(i,\"angular\",Object),\"module\",function(){var c={};return function(a,e,f){e&&c.hasOwnProperty(a)&&(c[a]=null);return d(c,a,function(){function b(a,b,d){return function(){c[d||\"push\"]([a,b,arguments]);return g}}if(!e)throw Error(\"No module: \"+a);var c=[],d=[],h=b(\"$injector\",\"invoke\"),g={_invokeQueue:c,_runBlocks:d,requires:e,name:a,provider:b(\"$provide\",\"provider\"),factory:b(\"$provide\",\"factory\"),service:b(\"$provide\",\"service\"),\n    value:b(\"$provide\",\"value\"),constant:b(\"$provide\",\"constant\",\"unshift\"),filter:b(\"$filterProvider\",\"register\"),directive:b(\"$compileProvider\",\"directive\"),config:h,run:function(a){d.push(a);return this}};f&&h(f);return g})}})})(window);\n\n    // include a third-party async loader library\n    /*!\n     * $script.js v1.3\n     * https://github.com/ded/script.js\n     * Copyright: @ded & @fat - Dustin Diaz, Jacob Thornton 2011\n     * Follow our software http://twitter.com/dedfat\n     * License: MIT\n     */\n    !function(a,b,c){function t(a,c){var e=b.createElement(\"script\"),f=j;e.onload=e.onerror=e[o]=function(){e[m]&&!/^c|loade/.test(e[m])||f||(e.onload=e[o]=null,f=1,c())},e.async=1,e.src=a,d.insertBefore(e,d.firstChild)}function q(a,b){p(a,function(a){return!b(a)})}var d=b.getElementsByTagName(\"head\")[0],e={},f={},g={},h={},i=\"string\",j=!1,k=\"push\",l=\"DOMContentLoaded\",m=\"readyState\",n=\"addEventListener\",o=\"onreadystatechange\",p=function(a,b){for(var c=0,d=a.length;c<d;++c)if(!b(a[c]))return j;return 1};!b[m]&&b[n]&&(b[n](l,function r(){b.removeEventListener(l,r,j),b[m]=\"complete\"},j),b[m]=\"loading\");var s=function(a,b,d){function o(){if(!--m){e[l]=1,j&&j();for(var a in g)p(a.split(\"|\"),n)&&!q(g[a],n)&&(g[a]=[])}}function n(a){return a.call?a():e[a]}a=a[k]?a:[a];var i=b&&b.call,j=i?b:d,l=i?a.join(\"\"):b,m=a.length;c(function(){q(a,function(a){h[a]?(l&&(f[l]=1),o()):(h[a]=1,l&&(f[l]=1),t(s.path?s.path+a+\".js\":a,o))})},0);return s};s.get=t,s.ready=function(a,b,c){a=a[k]?a:[a];var d=[];!q(a,function(a){e[a]||d[k](a)})&&p(a,function(a){return e[a]})?b():!function(a){g[a]=g[a]||[],g[a][k](b),c&&c(d)}(a.join(\"|\"));return s};var u=a.$script;s.noConflict=function(){a.$script=u;return this},typeof module!=\"undefined\"&&module.exports?module.exports=s:a.$script=s}(this,document,setTimeout)\n\n    // load all of the dependencies asynchronously.\n    $script([\n      'lib/angular/angular.js',\n      'js/app.js',\n      'js/services.js',\n      'js/controllers.js',\n      'js/filters.js',\n      'js/directives.js'\n    ], function() {\n      // when all is done, execute bootstrap angular application\n      angular.bootstrap(document, ['myApp']);\n    });\n  </script>\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\">\n</head>\n<body ng-cloak>\n  <ul class=\"menu\">\n    <li><a href=\"#/view1\">view1</a></li>\n    <li><a href=\"#/view2\">view2</a></li>\n  </ul>\n\n  <div ng-view></div>\n\n  <div>Angular seed app: v<span app-version></span></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "chapter5/recipe1/app/index.html",
    "content": "<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\"/>\n</head>\n<body ng-app=\"MyApp\">\n  <div ng-controller=\"PostsCtrl\">\n    <ul ng-repeat=\"post in posts\">\n      <li>{{post.title}}</li>      \n    </ul>\n  </div>\n\n  <script src=\"lib/angular/angular.js\"></script>\n  <script src=\"js/controllers.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "chapter5/recipe1/app/js/controllers.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.controller(\"PostsCtrl\", function($scope, $http) {\n  $http.defaults.headers.common[\"X-Custom-Header\"] = \"Angular.js\";\n  $http.get('data/posts.json').\n    success(function(data, status, headers, config) {\n      $scope.posts = data;\n    });\n});"
  },
  {
    "path": "chapter5/recipe1/app/lib/angular/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngCookies\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookies\n   * @requires $browser\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from\n   * this object, new cookies are created/deleted at the end of current $eval.\n   *\n   * @example\n   */\n   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for(name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            if (angular.isDefined(lastCookies[name])) {\n              cookies[name] = lastCookies[name];\n            } else {\n              delete cookies[name];\n            }\n          } else if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated){\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   * @example\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#get\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          return angular.fromJson($cookies[key]);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#put\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#remove\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter5/recipe1/app/lib/angular/angular-loader.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n\n(\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n'use strict';\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n)(window);\n\n/**\n * Closure compiler type information\n *\n * @typedef { {\n *   requires: !Array.<string>,\n *   invokeQueue: !Array.<Array.<*>>,\n *\n *   service: function(string, Function):angular.Module,\n *   factory: function(string, Function):angular.Module,\n *   value: function(string, *):angular.Module,\n *\n *   filter: function(string, Function):angular.Module,\n *\n *   init: function(Function):angular.Module\n * } }\n */\nangular.Module;\n\n"
  },
  {
    "path": "chapter5/recipe1/app/lib/angular/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g. \n *   `http://example.com:8080/api`), you'll need to escape the colon character before the port\n *   number, like this: `$resource('http://example.com\\\\:8080/api')`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` – {string} – The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` – {object=} – Optional set of pre-bound parameters for this action.\n *   - isArray – {boolean=} – If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n     * encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace((pctEncodeSpaces ? null : /%20/g), '+');\n    }\n\n    function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        action.method = angular.uppercase(action.method);\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter5/recipe1/app/lib/angular/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             '<p style=\"color:blue\">an html\\n' +\n             '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n             'snippet</p>';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n          Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n           <table>\n             <tr>\n               <td>Filter</td>\n               <td>Source</td>\n               <td>Rendered</td>\n             </tr>\n             <tr id=\"html-filter\">\n               <td>html filter</td>\n               <td>\n                 <pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre>\n               </td>\n               <td>\n                 <div ng-bind-html=\"snippet\"></div>\n               </td>\n             </tr>\n             <tr id=\"escaped-html\">\n               <td>no filter</td>\n               <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind=\"snippet\"></div></td>\n             </tr>\n             <tr id=\"html-unsafe-filter\">\n               <td>unsafe html filter</td>\n               <td><pre>&lt;div ng-bind-html-unsafe=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind-html-unsafe=\"snippet\"></div></td>\n             </tr>\n           </table>\n         </div>\n     </doc:source>\n     <doc:scenario>\n       it('should sanitize the html snippet ', function() {\n         expect(using('#html-filter').element('div').html()).\n           toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n       });\n\n       it('should escape snippet without any filter', function() {\n         expect(using('#escaped-html').element('div').html()).\n           toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n                \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n                \"snippet&lt;/p&gt;\");\n       });\n\n       it('should inline raw snippet if filtered as unsafe', function() {\n         expect(using('#html-unsafe-filter').element(\"div\").html()).\n           toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n                \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n                \"snippet</p>\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new <b>text</b>');\n         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');\n         expect(using('#escaped-html').element('div').html()).toBe(\"new &lt;b&gt;text&lt;/b&gt;\");\n         expect(using('#html-unsafe-filter').binding(\"snippet\")).toBe('new <b>text</b>');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar $sanitize = function(html) {\n  var buf = [];\n    htmlParser(html, htmlSanitizeWriter(buf));\n    return buf.join('');\n};\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP = /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  URI_REGEXP = /^((ftp|https?):\\/\\/|mailto:|#)/,\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g; // Match everything outside of normal chars and \" (quote character)\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,aside,\" +\n        \"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,\" +\n        \"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,bdi,bdo,\" +\n        \"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,\" +\n        \"span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        index = html.indexOf(\"-->\");\n\n        if ( index >= 0 ) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'), function(all, text){\n        text = text.\n          replace(COMMENT_REGEXP, \"$1\").\n          replace(CDATA_REGEXP, \"$1\");\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n\n        return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw \"Parse Error: \" + html;\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {\n      var value = doubleQuotedValue\n        || singleQoutedValue\n        || unqoutedValue\n        || '';\n\n      attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nvar hiddenPre=document.createElement(\"pre\");\nfunction decodeEntities(value) {\n  hiddenPre.innerHTML=value.replace(/</g,\"&lt;\");\n  return hiddenPre.innerText || hiddenPre.textContent || '';\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] == true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] == true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).value('$sanitize', $sanitize);\n\n/**\n * @ngdoc directive\n * @name ngSanitize.directive:ngBindHtml\n *\n * @description\n * Creates a binding that will sanitize the result of evaluating the `expression` with the\n * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n */\nangular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);\n    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {\n      value = $sanitize(value);\n      element.html(value || '');\n    });\n  };\n}]);\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n *   plain email address links.\n *\n * @param {string} text Input text.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should linkify the snippet with urls', function() {\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('Pretty text with some links:&#10;' +\n                '<a href=\"http://angularjs.org/\">http://angularjs.org/</a>,&#10;' +\n                '<a href=\"mailto:us@somewhere.org\">us@somewhere.org</a>,&#10;' +\n                '<a href=\"mailto:another@somewhere.org\">another@somewhere.org</a>,&#10;' +\n                'and one more: <a href=\"ftp://127.0.0.1/\">ftp://127.0.0.1/</a>.');\n       });\n\n       it ('should not linkify snippet without the linky filter', function() {\n         expect(using('#escaped-html').binding('snippet')).\n           toBe(\"Pretty text with some links:\\n\" +\n                \"http://angularjs.org/,\\n\" +\n                \"mailto:us@somewhere.org,\\n\" +\n                \"another@somewhere.org,\\n\" +\n                \"and one more: ftp://127.0.0.1/.\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new http://link.');\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('new <a href=\"http://link\">http://link</a>.');\n         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', function() {\n  var LINKY_URL_REGEXP = /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s\\.\\;\\,\\(\\)\\{\\}\\<\\>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    // TODO(vojta): use $sanitize instead\n    var writer = htmlSanitizeWriter(html);\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      writer.chars(raw.substr(0, i));\n      writer.start('a', {href:url});\n      writer.chars(match[0].replace(MAILTO_REGEXP, ''));\n      writer.end('a');\n      raw = raw.substring(i + match[0].length);\n    }\n    writer.chars(raw);\n    return html.join('');\n  };\n});\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter5/recipe1/app/lib/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter5/recipe1/app/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter5/recipe1/config/testacular-e2e.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  ANGULAR_SCENARIO,\n  ANGULAR_SCENARIO_ADAPTER,\n  'test/e2e/**/*.js'\n];\n\nautoWatch = false;\n\nbrowsers = ['Chrome'];\n\nsingleRun = true;\n\nproxies = {\n  '/': 'http://localhost:8000/'\n};\n\njunitReporter = {\n  outputFile: 'test_out/e2e.xml',\n  suite: 'e2e'\n};\n"
  },
  {
    "path": "chapter5/recipe1/config/testacular.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  JASMINE,\n  JASMINE_ADAPTER,\n  'app/lib/angular/angular.js',\n  'app/lib/angular/angular-*.js',\n  'test/lib/angular/angular-mocks.js',\n  'app/js/**/*.js',\n  'test/unit/**/*.js'\n];\n\nautoWatch = true;\n\nbrowsers = ['Chrome'];\n\njunitReporter = {\n  outputFile: 'test_out/unit.xml',\n  suite: 'unit'\n};\n"
  },
  {
    "path": "chapter5/recipe1/logs/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "chapter5/recipe1/scripts/e2e-test.bat",
    "content": "@echo off\n\nREM Windows script for running e2e tests\nREM You have to run server and capture some browser first\nREM\nREM Requirements:\nREM - NodeJS (http://nodejs.org/)\nREM - Testacular (npm install -g testacular)\n\nset BASE_DIR=%~dp0\ntestacular start \"%BASE_DIR%\\..\\config\\testacular-e2e.conf.js\" %*\n"
  },
  {
    "path": "chapter5/recipe1/scripts/e2e-test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular-e2e.conf.js $*\n"
  },
  {
    "path": "chapter5/recipe1/scripts/test.bat",
    "content": "@echo off\r\n\r\nREM Windows script for running unit tests\r\nREM You have to run server and capture some browser first\r\nREM\r\nREM Requirements:\r\nREM - NodeJS (http://nodejs.org/)\r\nREM - Testacular (npm install -g testacular)\r\n\r\nset BASE_DIR=%~dp0\r\ntestacular start \"%BASE_DIR%\\..\\config\\testacular.conf.js\" %*\r\n"
  },
  {
    "path": "chapter5/recipe1/scripts/test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular.conf.js $*\n"
  },
  {
    "path": "chapter5/recipe1/scripts/watchr.rb",
    "content": "#!/usr/bin/env watchr\n\n# config file for watchr http://github.com/mynyml/watchr\n# install: gem install watchr\n# run: watch watchr.rb\n# note: make sure that you have jstd server running (server.sh) and a browser captured\n\nlog_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log')\n\n`cd ..`\n`touch #{log_file}`\n\nputs \"String watchr... log file: #{log_file}\"\n\nwatch( '(app/js|test/unit)' )  do\n  `echo \"\\n\\ntest run started @ \\`date\\`\" > #{log_file}`\n  `scripts/test.sh &> #{log_file}`\nend\n\n"
  },
  {
    "path": "chapter5/recipe1/scripts/web-server.js",
    "content": "#!/usr/bin/env node\n\nvar util = require('util'),\n    http = require('http'),\n    fs = require('fs'),\n    url = require('url'),\n    events = require('events');\n\nvar DEFAULT_PORT = 8000;\n\nfunction main(argv) {\n  new HttpServer({\n    'GET': createServlet(StaticServlet),\n    'HEAD': createServlet(StaticServlet)\n  }).start(Number(argv[2]) || DEFAULT_PORT);\n}\n\nfunction escapeHtml(value) {\n  return value.toString().\n    replace('<', '&lt;').\n    replace('>', '&gt;').\n    replace('\"', '&quot;');\n}\n\nfunction createServlet(Class) {\n  var servlet = new Class();\n  return servlet.handleRequest.bind(servlet);\n}\n\n/**\n * An Http server implementation that uses a map of methods to decide\n * action routing.\n *\n * @param {Object} Map of method => Handler function\n */\nfunction HttpServer(handlers) {\n  this.handlers = handlers;\n  this.server = http.createServer(this.handleRequest_.bind(this));\n}\n\nHttpServer.prototype.start = function(port) {\n  this.port = port;\n  this.server.listen(port);\n  util.puts('Http Server running at http://localhost:' + port + '/');\n};\n\nHttpServer.prototype.parseUrl_ = function(urlString) {\n  var parsed = url.parse(urlString);\n  parsed.pathname = url.resolve('/', parsed.pathname);\n  return url.parse(url.format(parsed), true);\n};\n\nHttpServer.prototype.handleRequest_ = function(req, res) {\n  var logEntry = req.method + ' ' + req.url;\n  if (req.headers['user-agent']) {\n    logEntry += ' ' + req.headers['user-agent'];\n  }\n  util.puts(logEntry);\n  req.url = this.parseUrl_(req.url);\n  var handler = this.handlers[req.method];\n  if (!handler) {\n    res.writeHead(501);\n    res.end();\n  } else {\n    handler.call(this, req, res);\n  }\n};\n\n/**\n * Handles static content.\n */\nfunction StaticServlet() {}\n\nStaticServlet.MimeMap = {\n  'txt': 'text/plain',\n  'html': 'text/html',\n  'css': 'text/css',\n  'xml': 'application/xml',\n  'json': 'application/json',\n  'js': 'application/javascript',\n  'jpg': 'image/jpeg',\n  'jpeg': 'image/jpeg',\n  'gif': 'image/gif',\n  'png': 'image/png',\n  'svg': 'image/svg+xml'\n};\n\nStaticServlet.prototype.handleRequest = function(req, res) {\n  var self = this;\n  var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){\n    return String.fromCharCode(parseInt(hex, 16));\n  });\n  var parts = path.split('/');\n  if (parts[parts.length-1].charAt(0) === '.')\n    return self.sendForbidden_(req, res, path);\n  fs.stat(path, function(err, stat) {\n    if (err)\n      return self.sendMissing_(req, res, path);\n    if (stat.isDirectory())\n      return self.sendDirectory_(req, res, path);\n    return self.sendFile_(req, res, path);\n  });\n}\n\nStaticServlet.prototype.sendError_ = function(req, res, error) {\n  res.writeHead(500, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>Internal Server Error</title>\\n');\n  res.write('<h1>Internal Server Error</h1>');\n  res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');\n  util.puts('500 Internal Server Error');\n  util.puts(util.inspect(error));\n};\n\nStaticServlet.prototype.sendMissing_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(404, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>404 Not Found</title>\\n');\n  res.write('<h1>Not Found</h1>');\n  res.write(\n    '<p>The requested URL ' +\n    escapeHtml(path) +\n    ' was not found on this server.</p>'\n  );\n  res.end();\n  util.puts('404 Not Found: ' + path);\n};\n\nStaticServlet.prototype.sendForbidden_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(403, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>403 Forbidden</title>\\n');\n  res.write('<h1>Forbidden</h1>');\n  res.write(\n    '<p>You do not have permission to access ' +\n    escapeHtml(path) + ' on this server.</p>'\n  );\n  res.end();\n  util.puts('403 Forbidden: ' + path);\n};\n\nStaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {\n  res.writeHead(301, {\n      'Content-Type': 'text/html',\n      'Location': redirectUrl\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>301 Moved Permanently</title>\\n');\n  res.write('<h1>Moved Permanently</h1>');\n  res.write(\n    '<p>The document has moved <a href=\"' +\n    redirectUrl +\n    '\">here</a>.</p>'\n  );\n  res.end();\n  util.puts('301 Moved Permanently: ' + redirectUrl);\n};\n\nStaticServlet.prototype.sendFile_ = function(req, res, path) {\n  var self = this;\n  var file = fs.createReadStream(path);\n  res.writeHead(200, {\n    'Content-Type': StaticServlet.\n      MimeMap[path.split('.').pop()] || 'text/plain'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n  } else {\n    file.on('data', res.write.bind(res));\n    file.on('close', function() {\n      res.end();\n    });\n    file.on('error', function(error) {\n      self.sendError_(req, res, error);\n    });\n  }\n};\n\nStaticServlet.prototype.sendDirectory_ = function(req, res, path) {\n  var self = this;\n  if (path.match(/[^\\/]$/)) {\n    req.url.pathname += '/';\n    var redirectUrl = url.format(url.parse(url.format(req.url)));\n    return self.sendRedirect_(req, res, redirectUrl);\n  }\n  fs.readdir(path, function(err, files) {\n    if (err)\n      return self.sendError_(req, res, error);\n\n    if (!files.length)\n      return self.writeDirectoryIndex_(req, res, path, []);\n\n    var remaining = files.length;\n    files.forEach(function(fileName, index) {\n      fs.stat(path + '/' + fileName, function(err, stat) {\n        if (err)\n          return self.sendError_(req, res, err);\n        if (stat.isDirectory()) {\n          files[index] = fileName + '/';\n        }\n        if (!(--remaining))\n          return self.writeDirectoryIndex_(req, res, path, files);\n      });\n    });\n  });\n};\n\nStaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {\n  path = path.substring(1);\n  res.writeHead(200, {\n    'Content-Type': 'text/html'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n    return;\n  }\n  res.write('<!doctype html>\\n');\n  res.write('<title>' + escapeHtml(path) + '</title>\\n');\n  res.write('<style>\\n');\n  res.write('  ol { list-style-type: none; font-size: 1.2em; }\\n');\n  res.write('</style>\\n');\n  res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');\n  res.write('<ol>');\n  files.forEach(function(fileName) {\n    if (fileName.charAt(0) !== '.') {\n      res.write('<li><a href=\"' +\n        escapeHtml(fileName) + '\">' +\n        escapeHtml(fileName) + '</a></li>');\n    }\n  });\n  res.write('</ol>');\n  res.end();\n};\n\n// Must be last,\nmain(process.argv);\n"
  },
  {
    "path": "chapter5/recipe1/test/e2e/runner.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <title>End2end Test Runner</title>\n    <script src=\"../lib/angular/angular-scenario.js\" ng-autotest></script>\n    <script src=\"scenarios.js\"></script>\n  </head>\n  <body>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter5/recipe1/test/e2e/scenarios.js",
    "content": "'use strict';\n\n/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */\n\ndescribe('my app', function() {\n\n  beforeEach(function() {\n    browser().navigateTo('../../app/index.html');\n  });\n\n\n  it('should automatically redirect to /view1 when location hash/fragment is empty', function() {\n    expect(browser().location().url()).toBe(\"/view1\");\n  });\n\n\n  describe('view1', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view1');\n    });\n\n\n    it('should render view1 when user navigates to /view1', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 1/);\n    });\n\n  });\n\n\n  describe('view2', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view2');\n    });\n\n\n    it('should render view2 when user navigates to /view2', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 2/);\n    });\n\n  });\n});\n"
  },
  {
    "path": "chapter5/recipe1/test/lib/angular/angular-mocks.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n *\n * TODO(vojta): wrap whole file into closure during build\n */\n\n/**\n * @ngdoc overview\n * @name angular.mock\n * @description\n *\n * Namespace from 'angular-mocks.js' which contains testing related code.\n */\nangular.mock = {};\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ngMock.$browser\n *\n * @description\n * This service is a mock implementation of {@link ng.$browser}. It provides fake\n * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,\n * cookies, etc...\n *\n * The api of this service is the same as that of the real {@link ng.$browser $browser}, except\n * that there are several helper methods available which can be used in tests.\n */\nangular.mock.$BrowserProvider = function() {\n  this.$get = function(){\n    return new angular.mock.$Browser();\n  };\n};\n\nangular.mock.$Browser = function() {\n  var self = this;\n\n  this.isMock = true;\n  self.$$url = \"http://server/\";\n  self.$$lastUrl = self.$$url; // used by url polling fn\n  self.pollFns = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = angular.noop;\n  self.$$incOutstandingRequestCount = angular.noop;\n\n\n  // register url polling fn\n\n  self.onUrlChange = function(listener) {\n    self.pollFns.push(\n      function() {\n        if (self.$$lastUrl != self.$$url) {\n          self.$$lastUrl = self.$$url;\n          listener(self.$$url);\n        }\n      }\n    );\n\n    return listener;\n  };\n\n  self.cookieHash = {};\n  self.lastCookieHash = {};\n  self.deferredFns = [];\n  self.deferredNextId = 0;\n\n  self.defer = function(fn, delay) {\n    delay = delay || 0;\n    self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});\n    self.deferredFns.sort(function(a,b){ return a.time - b.time;});\n    return self.deferredNextId++;\n  };\n\n\n  self.defer.now = 0;\n\n\n  self.defer.cancel = function(deferId) {\n    var fnIndex;\n\n    angular.forEach(self.deferredFns, function(fn, index) {\n      if (fn.id === deferId) fnIndex = index;\n    });\n\n    if (fnIndex !== undefined) {\n      self.deferredFns.splice(fnIndex, 1);\n      return true;\n    }\n\n    return false;\n  };\n\n\n  /**\n   * @name ngMock.$browser#defer.flush\n   * @methodOf ngMock.$browser\n   *\n   * @description\n   * Flushes all pending requests and executes the defer callbacks.\n   *\n   * @param {number=} number of milliseconds to flush. See {@link #defer.now}\n   */\n  self.defer.flush = function(delay) {\n    if (angular.isDefined(delay)) {\n      self.defer.now += delay;\n    } else {\n      if (self.deferredFns.length) {\n        self.defer.now = self.deferredFns[self.deferredFns.length-1].time;\n      } else {\n        throw Error('No deferred tasks to be flushed');\n      }\n    }\n\n    while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {\n      self.deferredFns.shift().fn();\n    }\n  };\n  /**\n   * @name ngMock.$browser#defer.now\n   * @propertyOf ngMock.$browser\n   *\n   * @description\n   * Current milliseconds mock time.\n   */\n\n  self.$$baseHref = '';\n  self.baseHref = function() {\n    return this.$$baseHref;\n  };\n};\nangular.mock.$Browser.prototype = {\n\n/**\n  * @name ngMock.$browser#poll\n  * @methodOf ngMock.$browser\n  *\n  * @description\n  * run all fns in pollFns\n  */\n  poll: function poll() {\n    angular.forEach(this.pollFns, function(pollFn){\n      pollFn();\n    });\n  },\n\n  addPollFn: function(pollFn) {\n    this.pollFns.push(pollFn);\n    return pollFn;\n  },\n\n  url: function(url, replace) {\n    if (url) {\n      this.$$url = url;\n      return this;\n    }\n\n    return this.$$url;\n  },\n\n  cookies:  function(name, value) {\n    if (name) {\n      if (value == undefined) {\n        delete this.cookieHash[name];\n      } else {\n        if (angular.isString(value) &&       //strings only\n            value.length <= 4096) {          //strict cookie storage limits\n          this.cookieHash[name] = value;\n        }\n      }\n    } else {\n      if (!angular.equals(this.cookieHash, this.lastCookieHash)) {\n        this.lastCookieHash = angular.copy(this.cookieHash);\n        this.cookieHash = angular.copy(this.cookieHash);\n      }\n      return this.cookieHash;\n    }\n  },\n\n  notifyWhenNoOutstandingRequests: function(fn) {\n    fn();\n  }\n};\n\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandlerProvider\n *\n * @description\n * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed\n * into the `$exceptionHandler`.\n */\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandler\n *\n * @description\n * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed\n * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration\n * information.\n *\n *\n * <pre>\n *   describe('$exceptionHandlerProvider', function() {\n *\n *     it('should capture log messages and exceptions', function() {\n *\n *       module(function($exceptionHandlerProvider) {\n *         $exceptionHandlerProvider.mode('log');\n *       });\n *\n *       inject(function($log, $exceptionHandler, $timeout) {\n *         $timeout(function() { $log.log(1); });\n *         $timeout(function() { $log.log(2); throw 'banana peel'; });\n *         $timeout(function() { $log.log(3); });\n *         expect($exceptionHandler.errors).toEqual([]);\n *         expect($log.assertEmpty());\n *         $timeout.flush();\n *         expect($exceptionHandler.errors).toEqual(['banana peel']);\n *         expect($log.log.logs).toEqual([[1], [2], [3]]);\n *       });\n *     });\n *   });\n * </pre>\n */\n\nangular.mock.$ExceptionHandlerProvider = function() {\n  var handler;\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$exceptionHandlerProvider#mode\n   * @methodOf ngMock.$exceptionHandlerProvider\n   *\n   * @description\n   * Sets the logging mode.\n   *\n   * @param {string} mode Mode of operation, defaults to `rethrow`.\n   *\n   *   - `rethrow`: If any errors are are passed into the handler in tests, it typically\n   *                means that there is a bug in the application or test, so this mock will\n   *                make these tests fail.\n   *   - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores an\n   *            array of errors in `$exceptionHandler.errors`, to allow later assertion of them.\n   *            See {@link ngMock.$log#assertEmpty assertEmpty()} and\n   *             {@link ngMock.$log#reset reset()}\n   */\n  this.mode = function(mode) {\n    switch(mode) {\n      case 'rethrow':\n        handler = function(e) {\n          throw e;\n        };\n        break;\n      case 'log':\n        var errors = [];\n\n        handler = function(e) {\n          if (arguments.length == 1) {\n            errors.push(e);\n          } else {\n            errors.push([].slice.call(arguments, 0));\n          }\n        };\n\n        handler.errors = errors;\n        break;\n      default:\n        throw Error(\"Unknown mode '\" + mode + \"', only 'log'/'rethrow' modes are allowed!\");\n    }\n  };\n\n  this.$get = function() {\n    return handler;\n  };\n\n  this.mode('rethrow');\n};\n\n\n/**\n * @ngdoc service\n * @name ngMock.$log\n *\n * @description\n * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays\n * (one array per logging level). These arrays are exposed as `logs` property of each of the\n * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.\n *\n */\nangular.mock.$LogProvider = function() {\n\n  function concat(array1, array2, index) {\n    return array1.concat(Array.prototype.slice.call(array2, index));\n  }\n\n\n  this.$get = function () {\n    var $log = {\n      log: function() { $log.log.logs.push(concat([], arguments, 0)); },\n      warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },\n      info: function() { $log.info.logs.push(concat([], arguments, 0)); },\n      error: function() { $log.error.logs.push(concat([], arguments, 0)); }\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#reset\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Reset all of the logging arrays to empty.\n     */\n    $log.reset = function () {\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#log.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.log.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#warn.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.warn.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#info.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.info.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#error.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.error.logs = [];\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#assertEmpty\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.\n     */\n    $log.assertEmpty = function() {\n      var errors = [];\n      angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {\n        angular.forEach($log[logLevel].logs, function(log) {\n          angular.forEach(log, function (logItem) {\n            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\\n' + (logItem.stack || ''));\n          });\n        });\n      });\n      if (errors.length) {\n        errors.unshift(\"Expected $log to be empty! Either a message was logged unexpectedly, or an expected \" +\n          \"log message was not checked and removed:\");\n        errors.push('');\n        throw new Error(errors.join('\\n---------\\n'));\n      }\n    };\n\n    $log.reset();\n    return $log;\n  };\n};\n\n\n(function() {\n  var R_ISO8061_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?:\\:?(\\d\\d)(?:\\:?(\\d\\d)(?:\\.(\\d{3}))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d)))?$/;\n\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8061_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n  function int(str) {\n    return parseInt(str, 10);\n  }\n\n  function padNumber(num, digits, trim) {\n    var neg = '';\n    if (num < 0) {\n      neg =  '-';\n      num = -num;\n    }\n    num = '' + num;\n    while(num.length < digits) num = '0' + num;\n    if (trim)\n      num = num.substr(num.length - digits);\n    return neg + num;\n  }\n\n\n  /**\n   * @ngdoc object\n   * @name angular.mock.TzDate\n   * @description\n   *\n   * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.\n   *\n   * Mock of the Date type which has its timezone specified via constroctor arg.\n   *\n   * The main purpose is to create Date-like instances with timezone fixed to the specified timezone\n   * offset, so that we can test code that depends on local timezone settings without dependency on\n   * the time zone settings of the machine where the code is running.\n   *\n   * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)\n   * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*\n   *\n   * @example\n   * !!!! WARNING !!!!!\n   * This is not a complete Date object so only methods that were implemented can be called safely.\n   * To make matters worse, TzDate instances inherit stuff from Date via a prototype.\n   *\n   * We do our best to intercept calls to \"unimplemented\" methods, but since the list of methods is\n   * incomplete we might be missing some non-standard methods. This can result in errors like:\n   * \"Date.prototype.foo called on incompatible Object\".\n   *\n   * <pre>\n   * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');\n   * newYearInBratislava.getTimezoneOffset() => -60;\n   * newYearInBratislava.getFullYear() => 2010;\n   * newYearInBratislava.getMonth() => 0;\n   * newYearInBratislava.getDate() => 1;\n   * newYearInBratislava.getHours() => 0;\n   * newYearInBratislava.getMinutes() => 0;\n   * </pre>\n   *\n   */\n  angular.mock.TzDate = function (offset, timestamp) {\n    var self = new Date(0);\n    if (angular.isString(timestamp)) {\n      var tsStr = timestamp;\n\n      self.origDate = jsonStringToDate(timestamp);\n\n      timestamp = self.origDate.getTime();\n      if (isNaN(timestamp))\n        throw {\n          name: \"Illegal Argument\",\n          message: \"Arg '\" + tsStr + \"' passed into TzDate constructor is not a valid date string\"\n        };\n    } else {\n      self.origDate = new Date(timestamp);\n    }\n\n    var localOffset = new Date(timestamp).getTimezoneOffset();\n    self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;\n    self.date = new Date(timestamp + self.offsetDiff);\n\n    self.getTime = function() {\n      return self.date.getTime() - self.offsetDiff;\n    };\n\n    self.toLocaleDateString = function() {\n      return self.date.toLocaleDateString();\n    };\n\n    self.getFullYear = function() {\n      return self.date.getFullYear();\n    };\n\n    self.getMonth = function() {\n      return self.date.getMonth();\n    };\n\n    self.getDate = function() {\n      return self.date.getDate();\n    };\n\n    self.getHours = function() {\n      return self.date.getHours();\n    };\n\n    self.getMinutes = function() {\n      return self.date.getMinutes();\n    };\n\n    self.getSeconds = function() {\n      return self.date.getSeconds();\n    };\n\n    self.getTimezoneOffset = function() {\n      return offset * 60;\n    };\n\n    self.getUTCFullYear = function() {\n      return self.origDate.getUTCFullYear();\n    };\n\n    self.getUTCMonth = function() {\n      return self.origDate.getUTCMonth();\n    };\n\n    self.getUTCDate = function() {\n      return self.origDate.getUTCDate();\n    };\n\n    self.getUTCHours = function() {\n      return self.origDate.getUTCHours();\n    };\n\n    self.getUTCMinutes = function() {\n      return self.origDate.getUTCMinutes();\n    };\n\n    self.getUTCSeconds = function() {\n      return self.origDate.getUTCSeconds();\n    };\n\n    self.getUTCMilliseconds = function() {\n      return self.origDate.getUTCMilliseconds();\n    };\n\n    self.getDay = function() {\n      return self.date.getDay();\n    };\n\n    // provide this method only on browsers that already have it\n    if (self.toISOString) {\n      self.toISOString = function() {\n        return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +\n              padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +\n              padNumber(self.origDate.getUTCDate(), 2) + 'T' +\n              padNumber(self.origDate.getUTCHours(), 2) + ':' +\n              padNumber(self.origDate.getUTCMinutes(), 2) + ':' +\n              padNumber(self.origDate.getUTCSeconds(), 2) + '.' +\n              padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'\n      }\n    }\n\n    //hide all methods not implemented in this mock that the Date prototype exposes\n    var unimplementedMethods = ['getMilliseconds', 'getUTCDay',\n        'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',\n        'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',\n        'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',\n        'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',\n        'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];\n\n    angular.forEach(unimplementedMethods, function(methodName) {\n      self[methodName] = function() {\n        throw Error(\"Method '\" + methodName + \"' is not implemented in the TzDate mock\");\n      };\n    });\n\n    return self;\n  };\n\n  //make \"tzDateInstance instanceof Date\" return true\n  angular.mock.TzDate.prototype = Date.prototype;\n})();\n\n\n/**\n * @ngdoc function\n * @name angular.mock.dump\n * @description\n *\n * *NOTE*: this is not an injectable instance, just a globally available function.\n *\n * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.\n *\n * This method is also available on window, where it can be used to display objects on debug console.\n *\n * @param {*} object - any object to turn into string.\n * @return {string} a serialized string of the argument\n */\nangular.mock.dump = function(object) {\n  return serialize(object);\n\n  function serialize(object) {\n    var out;\n\n    if (angular.isElement(object)) {\n      object = angular.element(object);\n      out = angular.element('<div></div>');\n      angular.forEach(object, function(element) {\n        out.append(angular.element(element).clone());\n      });\n      out = out.html();\n    } else if (angular.isArray(object)) {\n      out = [];\n      angular.forEach(object, function(o) {\n        out.push(serialize(o));\n      });\n      out = '[ ' + out.join(', ') + ' ]';\n    } else if (angular.isObject(object)) {\n      if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {\n        out = serializeScope(object);\n      } else if (object instanceof Error) {\n        out = object.stack || ('' + object.name + ': ' + object.message);\n      } else {\n        out = angular.toJson(object, true);\n      }\n    } else {\n      out = String(object);\n    }\n\n    return out;\n  }\n\n  function serializeScope(scope, offset) {\n    offset = offset ||  '  ';\n    var log = [offset + 'Scope(' + scope.$id + '): {'];\n    for ( var key in scope ) {\n      if (scope.hasOwnProperty(key) && !key.match(/^(\\$|this)/)) {\n        log.push('  ' + key + ': ' + angular.toJson(scope[key]));\n      }\n    }\n    var child = scope.$$childHead;\n    while(child) {\n      log.push(serializeScope(child, offset + '  '));\n      child = child.$$nextSibling;\n    }\n    log.push('}');\n    return log.join('\\n' + offset);\n  }\n};\n\n/**\n * @ngdoc object\n * @name ngMock.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for unit testing application that use the\n * {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less\n * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.\n *\n * During unit testing, we want our unit tests to run quickly and have no external dependencies so\n * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or\n * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is\n * to verify whether a certain request has been sent or not, or alternatively just let the\n * application make requests, respond with pre-trained responses and assert that the end result is\n * what we expect it to be.\n *\n * This mock implementation can be used to respond with static or dynamic responses via the\n * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).\n *\n * When an Angular application needs some data from a server, it calls the $http service, which\n * sends the request to a real server using $httpBackend service. With dependency injection, it is\n * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify\n * the requests and respond with some testing data without sending a request to real server.\n *\n * There are two ways to specify what test data should be returned as http responses by the mock\n * backend when the code under test makes http requests:\n *\n * - `$httpBackend.expect` - specifies a request expectation\n * - `$httpBackend.when` - specifies a backend definition\n *\n *\n * # Request Expectations vs Backend Definitions\n *\n * Request expectations provide a way to make assertions about requests made by the application and\n * to define responses for those requests. The test will fail if the expected requests are not made\n * or they are made in the wrong order.\n *\n * Backend definitions allow you to define a fake backend for your application which doesn't assert\n * if a particular request was made or not, it just returns a trained response if a request is made.\n * The test will pass whether or not the request gets made during testing.\n *\n *\n * <table class=\"table\">\n *   <tr><th width=\"220px\"></th><th>Request expectations</th><th>Backend definitions</th></tr>\n *   <tr>\n *     <th>Syntax</th>\n *     <td>.expect(...).respond(...)</td>\n *     <td>.when(...).respond(...)</td>\n *   </tr>\n *   <tr>\n *     <th>Typical usage</th>\n *     <td>strict unit tests</td>\n *     <td>loose (black-box) unit testing</td>\n *   </tr>\n *   <tr>\n *     <th>Fulfills multiple requests</th>\n *     <td>NO</td>\n *     <td>YES</td>\n *   </tr>\n *   <tr>\n *     <th>Order of requests matters</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Request required</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Response required</th>\n *     <td>optional (see below)</td>\n *     <td>YES</td>\n *   </tr>\n * </table>\n *\n * In cases where both backend definitions and request expectations are specified during unit\n * testing, the request expectations are evaluated first.\n *\n * If a request expectation has no response specified, the algorithm will search your backend\n * definitions for an appropriate response.\n *\n * If a request didn't match any expectation or if the expectation doesn't have the response\n * defined, the backend definitions are evaluated in sequential order to see if any of them match\n * the request. The response from the first matched definition is returned.\n *\n *\n * # Flushing HTTP requests\n *\n * The $httpBackend used in production, always responds to requests with responses asynchronously.\n * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are\n * hard to write, follow and maintain. At the same time the testing mock, can't respond\n * synchronously because that would change the execution of the code under test. For this reason the\n * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending\n * requests and thus preserving the async api of the backend, while allowing the test to execute\n * synchronously.\n *\n *\n * # Unit testing with mock $httpBackend\n *\n * <pre>\n   // controller\n   function MyController($scope, $http) {\n     $http.get('/auth.py').success(function(data) {\n       $scope.user = data;\n     });\n\n     this.saveMessage = function(message) {\n       $scope.status = 'Saving...';\n       $http.post('/add-msg.py', message).success(function(response) {\n         $scope.status = '';\n       }).error(function() {\n         $scope.status = 'ERROR!';\n       });\n     };\n   }\n\n   // testing controller\n   var $httpBackend;\n\n   beforeEach(inject(function($injector) {\n     $httpBackend = $injector.get('$httpBackend');\n\n     // backend definition common for all tests\n     $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});\n   }));\n\n\n   afterEach(function() {\n     $httpBackend.verifyNoOutstandingExpectation();\n     $httpBackend.verifyNoOutstandingRequest();\n   });\n\n\n   it('should fetch authentication token', function() {\n     $httpBackend.expectGET('/auth.py');\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n   });\n\n\n   it('should send msg to server', function() {\n     // now you don’t care about the authentication, but\n     // the controller will still send the request and\n     // $httpBackend will respond without you having to\n     // specify the expectation and response for this request\n     $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');\n\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n     controller.saveMessage('message content');\n     expect(controller.status).toBe('Saving...');\n     $httpBackend.flush();\n     expect(controller.status).toBe('');\n   });\n\n\n   it('should send auth header', function() {\n     $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {\n       // check if the header was send, if it wasn't the expectation won't\n       // match the request and the test will fail\n       return headers['Authorization'] == 'xxx';\n     }).respond(201, '');\n\n     var controller = scope.$new(MyController);\n     controller.saveMessage('whatever');\n     $httpBackend.flush();\n   });\n   </pre>\n */\nangular.mock.$HttpBackendProvider = function() {\n  this.$get = [createHttpBackendMock];\n};\n\n/**\n * General factory function for $httpBackend mock.\n * Returns instance for unit testing (when no arguments specified):\n *   - passing through is disabled\n *   - auto flushing is disabled\n *\n * Returns instance for e2e testing (when `$delegate` and `$browser` specified):\n *   - passing through (delegating request to real backend) is enabled\n *   - auto flushing is enabled\n *\n * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)\n * @param {Object=} $browser Auto-flushing enabled if specified\n * @return {Object} Instance of $httpBackend mock\n */\nfunction createHttpBackendMock($delegate, $browser) {\n  var definitions = [],\n      expectations = [],\n      responses = [],\n      responsesPush = angular.bind(responses, responses.push);\n\n  function createResponse(status, data, headers) {\n    if (angular.isFunction(status)) return status;\n\n    return function() {\n      return angular.isNumber(status)\n          ? [status, data, headers]\n          : [200, status, data];\n    };\n  }\n\n  // TODO(vojta): change params to: method, url, data, headers, callback\n  function $httpBackend(method, url, data, callback, headers) {\n    var xhr = new MockXhr(),\n        expectation = expectations[0],\n        wasExpected = false;\n\n    function prettyPrint(data) {\n      return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)\n          ? data\n          : angular.toJson(data);\n    }\n\n    if (expectation && expectation.match(method, url)) {\n      if (!expectation.matchData(data))\n        throw Error('Expected ' + expectation + ' with different data\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.data) + '\\nGOT:      ' + data);\n\n      if (!expectation.matchHeaders(headers))\n        throw Error('Expected ' + expectation + ' with different headers\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.headers) + '\\nGOT:      ' +\n            prettyPrint(headers));\n\n      expectations.shift();\n\n      if (expectation.response) {\n        responses.push(function() {\n          var response = expectation.response(method, url, data, headers);\n          xhr.$$respHeaders = response[2];\n          callback(response[0], response[1], xhr.getAllResponseHeaders());\n        });\n        return;\n      }\n      wasExpected = true;\n    }\n\n    var i = -1, definition;\n    while ((definition = definitions[++i])) {\n      if (definition.match(method, url, data, headers || {})) {\n        if (definition.response) {\n          // if $browser specified, we do auto flush all requests\n          ($browser ? $browser.defer : responsesPush)(function() {\n            var response = definition.response(method, url, data, headers);\n            xhr.$$respHeaders = response[2];\n            callback(response[0], response[1], xhr.getAllResponseHeaders());\n          });\n        } else if (definition.passThrough) {\n          $delegate(method, url, data, callback, headers);\n        } else throw Error('No response defined !');\n        return;\n      }\n    }\n    throw wasExpected ?\n        Error('No response defined !') :\n        Error('Unexpected request: ' + method + ' ' + url + '\\n' +\n              (expectation ? 'Expected ' + expectation : 'No more request expected'));\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#when\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current definition.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.when = function(method, url, data, headers) {\n    var definition = new MockHttpExpectation(method, url, data, headers),\n        chain = {\n          respond: function(status, data, headers) {\n            definition.response = createResponse(status, data, headers);\n          }\n        };\n\n    if ($browser) {\n      chain.passThrough = function() {\n        definition.passThrough = true;\n      };\n    }\n\n    definitions.push(definition);\n    return chain;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for GET requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for HEAD requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for DELETE requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for POST requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for PUT requests.  For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for JSONP requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n  createShortMethods('when');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expect\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current expectation.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *  request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.expect = function(method, url, data, headers) {\n    var expectation = new MockHttpExpectation(method, url, data, headers);\n    expectations.push(expectation);\n    return {\n      respond: function(status, data, headers) {\n        expectation.response = createResponse(status, data, headers);\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for GET requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled. See #expect for more info.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for HEAD requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for DELETE requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for POST requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PUT requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPATCH\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PATCH requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for JSONP requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n  createShortMethods('expect');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#flush\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Flushes all pending requests using the trained responses.\n   *\n   * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,\n   *   all pending requests will be flushed. If there are no pending requests when the flush method\n   *   is called an exception is thrown (as this typically a sign of programming error).\n   */\n  $httpBackend.flush = function(count) {\n    if (!responses.length) throw Error('No pending request to flush !');\n\n    if (angular.isDefined(count)) {\n      while (count--) {\n        if (!responses.length) throw Error('No more pending request to flush !');\n        responses.shift()();\n      }\n    } else {\n      while (responses.length) {\n        responses.shift()();\n      }\n    }\n    $httpBackend.verifyNoOutstandingExpectation();\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingExpectation\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that all of the requests defined via the `expect` api were made. If any of the\n   * requests were not made, verifyNoOutstandingExpectation throws an exception.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyExpectations);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingExpectation = function() {\n    if (expectations.length) {\n      throw Error('Unsatisfied requests: ' + expectations.join(', '));\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingRequest\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that there are no outstanding requests that need to be flushed.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyNoOutstandingRequest);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingRequest = function() {\n    if (responses.length) {\n      throw Error('Unflushed requests: ' + responses.length);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#resetExpectations\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Resets all request expectations, but preserves all backend definitions. Typically, you would\n   * call resetExpectations during a multiple-phase test when you want to reuse the same instance of\n   * $httpBackend mock.\n   */\n  $httpBackend.resetExpectations = function() {\n    expectations.length = 0;\n    responses.length = 0;\n  };\n\n  return $httpBackend;\n\n\n  function createShortMethods(prefix) {\n    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {\n     $httpBackend[prefix + method] = function(url, headers) {\n       return $httpBackend[prefix](method, url, undefined, headers)\n     }\n    });\n\n    angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {\n      $httpBackend[prefix + method] = function(url, data, headers) {\n        return $httpBackend[prefix](method, url, data, headers)\n      }\n    });\n  }\n}\n\nfunction MockHttpExpectation(method, url, data, headers) {\n\n  this.data = data;\n  this.headers = headers;\n\n  this.match = function(m, u, d, h) {\n    if (method != m) return false;\n    if (!this.matchUrl(u)) return false;\n    if (angular.isDefined(d) && !this.matchData(d)) return false;\n    if (angular.isDefined(h) && !this.matchHeaders(h)) return false;\n    return true;\n  };\n\n  this.matchUrl = function(u) {\n    if (!url) return true;\n    if (angular.isFunction(url.test)) return url.test(u);\n    return url == u;\n  };\n\n  this.matchHeaders = function(h) {\n    if (angular.isUndefined(headers)) return true;\n    if (angular.isFunction(headers)) return headers(h);\n    return angular.equals(headers, h);\n  };\n\n  this.matchData = function(d) {\n    if (angular.isUndefined(data)) return true;\n    if (data && angular.isFunction(data.test)) return data.test(d);\n    if (data && !angular.isString(data)) return angular.toJson(data) == d;\n    return data == d;\n  };\n\n  this.toString = function() {\n    return method + ' ' + url;\n  };\n}\n\nfunction MockXhr() {\n\n  // hack for testing $http, $httpBackend\n  MockXhr.$$lastInstance = this;\n\n  this.open = function(method, url, async) {\n    this.$$method = method;\n    this.$$url = url;\n    this.$$async = async;\n    this.$$reqHeaders = {};\n    this.$$respHeaders = {};\n  };\n\n  this.send = function(data) {\n    this.$$data = data;\n  };\n\n  this.setRequestHeader = function(key, value) {\n    this.$$reqHeaders[key] = value;\n  };\n\n  this.getResponseHeader = function(name) {\n    // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last\n    var header = this.$$respHeaders[name];\n    if (header) return header;\n\n    name = angular.lowercase(name);\n    header = this.$$respHeaders[name];\n    if (header) return header;\n\n    header = undefined;\n    angular.forEach(this.$$respHeaders, function(headerVal, headerName) {\n      if (!header && angular.lowercase(headerName) == name) header = headerVal;\n    });\n    return header;\n  };\n\n  this.getAllResponseHeaders = function() {\n    var lines = [];\n\n    angular.forEach(this.$$respHeaders, function(value, key) {\n      lines.push(key + ': ' + value);\n    });\n    return lines.join('\\n');\n  };\n\n  this.abort = angular.noop;\n}\n\n\n/**\n * @ngdoc function\n * @name ngMock.$timeout\n * @description\n *\n * This service is just a simple decorator for {@link ng.$timeout $timeout} service\n * that adds a \"flush\" method.\n */\n\n/**\n * @ngdoc method\n * @name ngMock.$timeout#flush\n * @methodOf ngMock.$timeout\n * @description\n *\n * Flushes the queue of pending tasks.\n */\n\n/**\n *\n */\nangular.mock.$RootElementProvider = function() {\n  this.$get = function() {\n    return angular.element('<div ng-app></div>');\n  }\n};\n\n/**\n * @ngdoc overview\n * @name ngMock\n * @description\n *\n * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful\n * mocks to the {@link AUTO.$injector $injector}.\n */\nangular.module('ngMock', ['ng']).provider({\n  $browser: angular.mock.$BrowserProvider,\n  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,\n  $log: angular.mock.$LogProvider,\n  $httpBackend: angular.mock.$HttpBackendProvider,\n  $rootElement: angular.mock.$RootElementProvider\n}).config(function($provide) {\n  $provide.decorator('$timeout', function($delegate, $browser) {\n    $delegate.flush = function() {\n      $browser.defer.flush();\n    };\n    return $delegate;\n  });\n});\n\n\n/**\n * @ngdoc overview\n * @name ngMockE2E\n * @description\n *\n * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.\n * Currently there is only one mock present in this module -\n * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.\n */\nangular.module('ngMockE2E', ['ng']).config(function($provide) {\n  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);\n});\n\n/**\n * @ngdoc object\n * @name ngMockE2E.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of\n * applications that use the {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for unit testing please see\n * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.\n *\n * This implementation can be used to respond with static or dynamic responses via the `when` api\n * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the\n * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch\n * templates from a webserver).\n *\n * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application\n * is being developed with the real backend api replaced with a mock, it is often desirable for\n * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch\n * templates or static files from the webserver). To configure the backend with this behavior\n * use the `passThrough` request handler of `when` instead of `respond`.\n *\n * Additionally, we don't want to manually have to flush mocked out requests like we do during unit\n * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests\n * automatically, closely simulating the behavior of the XMLHttpRequest object.\n *\n * To setup the application to run with this http backend, you have to create a module that depends\n * on the `ngMockE2E` and your application modules and defines the fake backend:\n *\n * <pre>\n *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);\n *   myAppDev.run(function($httpBackend) {\n *     phones = [{name: 'phone1'}, {name: 'phone2'}];\n *\n *     // returns the current list of phones\n *     $httpBackend.whenGET('/phones').respond(phones);\n *\n *     // adds a new phone to the phones array\n *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {\n *       phones.push(angular.fromJSON(data));\n *     });\n *     $httpBackend.whenGET(/^\\/templates\\//).passThrough();\n *     //...\n *   });\n * </pre>\n *\n * Afterwards, bootstrap your app with this new module.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#when\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition.\n *\n * @param {string} method HTTP method.\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n *   object and returns true if the headers match the current definition.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n *\n *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n *    – The respond method takes a set of static data to be returned or a function that can return\n *    an array containing response status (number), response data (string) and response headers\n *    (Object).\n *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`\n *    handler, will be pass through to the real backend (an XHR request will be made to the\n *    server.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenGET\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for GET requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenHEAD\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for HEAD requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenDELETE\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for DELETE requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPOST\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for POST requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPUT\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PUT requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPATCH\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PATCH requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenJSONP\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for JSONP requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\nangular.mock.e2e = {};\nangular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];\n\n\nangular.mock.clearDataCache = function() {\n  var key,\n      cache = angular.element.cache;\n\n  for(key in cache) {\n    if (cache.hasOwnProperty(key)) {\n      var handle = cache[key].handle;\n\n      handle && angular.element(handle.elem).unbind();\n      delete cache[key];\n    }\n  }\n};\n\n\nwindow.jstestdriver && (function(window) {\n  /**\n   * Global method to output any number of objects into JSTD console. Useful for debugging.\n   */\n  window.dump = function() {\n    var args = [];\n    angular.forEach(arguments, function(arg) {\n      args.push(angular.mock.dump(arg));\n    });\n    jstestdriver.console.log.apply(jstestdriver.console, args);\n    if (window.console) {\n      window.console.log.apply(window.console, args);\n    }\n  };\n})(window);\n\n\nwindow.jasmine && (function(window) {\n\n  afterEach(function() {\n    var spec = getCurrentSpec();\n    var injector = spec.$injector;\n\n    spec.$injector = null;\n    spec.$modules = null;\n\n    if (injector) {\n      injector.get('$rootElement').unbind();\n      injector.get('$browser').pollFns.length = 0;\n    }\n\n    angular.mock.clearDataCache();\n\n    // clean up jquery's fragment cache\n    angular.forEach(angular.element.fragments, function(val, key) {\n      delete angular.element.fragments[key];\n    });\n\n    MockXhr.$$lastInstance = null;\n\n    angular.forEach(angular.callbacks, function(val, key) {\n      delete angular.callbacks[key];\n    });\n    angular.callbacks.counter = 0;\n  });\n\n  function getCurrentSpec() {\n    return jasmine.getEnv().currentSpec;\n  }\n\n  function isSpecRunning() {\n    var spec = getCurrentSpec();\n    return spec && spec.queue.running;\n  }\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.module\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * This function registers a module configuration code. It collects the configuration information\n   * which will be used when the injector is created by {@link angular.mock.inject inject}.\n   *\n   * See {@link angular.mock.inject inject} for usage example\n   *\n   * @param {...(string|Function)} fns any number of modules which are represented as string\n   *        aliases or as anonymous module initialization functions. The modules are used to\n   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.\n   */\n  window.module = angular.mock.module = function() {\n    var moduleFns = Array.prototype.slice.call(arguments, 0);\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      if (spec.$injector) {\n        throw Error('Injector already created, can not register a module!');\n      } else {\n        var modules = spec.$modules || (spec.$modules = []);\n        angular.forEach(moduleFns, function(module) {\n          modules.push(module);\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.inject\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * The inject function wraps a function into an injectable function. The inject() creates new\n   * instance of {@link AUTO.$injector $injector} per test, which is then used for\n   * resolving references.\n   *\n   * See also {@link angular.mock.module module}\n   *\n   * Example of what a typical jasmine tests looks like with the inject method.\n   * <pre>\n   *\n   *   angular.module('myApplicationModule', [])\n   *       .value('mode', 'app')\n   *       .value('version', 'v1.0.1');\n   *\n   *\n   *   describe('MyApp', function() {\n   *\n   *     // You need to load modules that you want to test,\n   *     // it loads only the \"ng\" module by default.\n   *     beforeEach(module('myApplicationModule'));\n   *\n   *\n   *     // inject() is used to inject arguments of all given functions\n   *     it('should provide a version', inject(function(mode, version) {\n   *       expect(version).toEqual('v1.0.1');\n   *       expect(mode).toEqual('app');\n   *     }));\n   *\n   *\n   *     // The inject and module method can also be used inside of the it or beforeEach\n   *     it('should override a version and test the new version is injected', function() {\n   *       // module() takes functions or strings (module aliases)\n   *       module(function($provide) {\n   *         $provide.value('version', 'overridden'); // override version here\n   *       });\n   *\n   *       inject(function(version) {\n   *         expect(version).toEqual('overridden');\n   *       });\n   *     ));\n   *   });\n   *\n   * </pre>\n   *\n   * @param {...Function} fns any number of functions which will be injected using the injector.\n   */\n  window.inject = angular.mock.inject = function() {\n    var blockFns = Array.prototype.slice.call(arguments, 0);\n    var errorForStack = new Error('Declaration Location');\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      var modules = spec.$modules || [];\n      modules.unshift('ngMock');\n      modules.unshift('ng');\n      var injector = spec.$injector;\n      if (!injector) {\n        injector = spec.$injector = angular.injector(modules);\n      }\n      for(var i = 0, ii = blockFns.length; i < ii; i++) {\n        try {\n          injector.invoke(blockFns[i] || angular.noop, this);\n        } catch (e) {\n          if(e.stack) e.stack +=  '\\n' + errorForStack.stack;\n          throw e;\n        } finally {\n          errorForStack = null;\n        }\n      }\n    }\n  };\n})(window);\n"
  },
  {
    "path": "chapter5/recipe1/test/lib/angular/angular-scenario.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Mar 21 12:46:34 2012 -0700\n */\n(function( window, undefined ) {\n'use strict';\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.7.2\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in array && array[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n\t\tvar exec,\n\t\t\tbulk = key == null,\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\n\t\t// Sets many values\n\t\tif ( key && typeof key === \"object\" ) {\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n\t\t\t}\n\t\t\tchainable = 1;\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = pass === undefined && jQuery.isFunction( value );\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations only iterate when executing function values\n\t\t\t\tif ( exec ) {\n\t\t\t\t\texec = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn exec.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\n\t\t\t\t// Otherwise they run against the entire set\n\t\t\t\t} else {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor (; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchainable = 1;\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfired = true;\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar length = list.length;\n\t\t\t\t\tadd( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory || memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tfragment,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tpixelMargin: true\n\t};\n\n\t// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead\n\tjQuery.boxModel = support.boxModel = (document.compatMode === \"CSS1Compat\");\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor ( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\tfragment.removeChild( div );\n\n\t// Null elements to avoid leaks in IE\n\tfragment = select = opt = div = input = null;\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tmarginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,\n\t\t\tpaddingMarginBorderVisibility, paddingMarginBorder,\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tconMarginTop = 1;\n\t\tpaddingMarginBorder = \"padding:0;margin:0;border:\";\n\t\tpositionTopLeftWidthHeight = \"position:absolute;top:0;left:0;width:1px;height:1px;\";\n\t\tpaddingMarginBorderVisibility = paddingMarginBorder + \"0;visibility:hidden;\";\n\t\tstyle = \"style='\" + positionTopLeftWidthHeight + paddingMarginBorder + \"5px solid #000;\";\n\t\thtml = \"<div \" + style + \"display:block;'><div style='\" + paddingMarginBorder + \"0;display:block;overflow:hidden;'></div></div>\" +\n\t\t\t\"<table \" + style + \"' cellpadding='0' cellspacing='0'>\" +\n\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = paddingMarginBorderVisibility + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td style='\" + paddingMarginBorder + \"0;display:none'></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName( \"td\" );\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t// gets computed margin-right based on width of container. For more\n\t\t// info see bug #3333\n\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tmarginDiv = document.createElement( \"div\" );\n\t\t\tmarginDiv.style.width = \"0\";\n\t\t\tmarginDiv.style.marginRight = \"0\";\n\t\t\tdiv.style.width = \"2px\";\n\t\t\tdiv.appendChild( marginDiv );\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\t// (IE < 8 does this)\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.width = div.style.padding = \"1px\";\n\t\t\tdiv.style.border = 0;\n\t\t\tdiv.style.overflow = \"hidden\";\n\t\t\tdiv.style.display = \"inline\";\n\t\t\tdiv.style.zoom = 1;\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.style.overflow = \"visible\";\n\t\t\tdiv.innerHTML = \"<div style='width:5px;'></div>\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\t\t}\n\n\t\tdiv.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;\n\t\tdiv.innerHTML = html;\n\n\t\touter = div.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.style.marginTop = \"1%\";\n\t\t\tsupport.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== \"1%\";\n\t\t}\n\n\t\tif ( typeof container.style.zoom !== \"undefined\" ) {\n\t\t\tcontainer.style.zoom = 1;\n\t\t}\n\n\t\tbody.removeChild( container );\n\t\tmarginDiv = div = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\treturn support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ internalKey ] : internalKey;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ internalKey ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( internalKey );\n\t\t\t} else {\n\t\t\t\telem[ internalKey ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, part, attr, name, l,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = elem.attributes;\n\t\t\t\t\tfor ( l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split( \".\", 2 );\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\t\tpart = parts[1] + \"!\";\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\tdata = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\tif ( data === undefined && elem ) {\n\t\t\t\t\tdata = jQuery.data( elem, key );\n\t\t\t\t\tdata = dataAttr( elem, key, data );\n\t\t\t\t}\n\n\t\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\t\tdata;\n\t\t\t}\n\n\t\t\tparts[1] = value;\n\t\t\tthis.each(function() {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.triggerHandler( \"setData\" + part, parts );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + part, parts );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, false );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\thooks = {};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( object );\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, l, isBool,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\t\t\tattrNames = value.toLowerCase().split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tisBool = rboolean.test( name );\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\t// Do not do this for boolean attributes (see #10870)\n\t\t\t\t\tif ( !isBool ) {\n\t\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\t}\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( isBool && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true,\n\t\tcoords: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = \"\" + value );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+)?\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\tvar attrs = elem.attributes || {};\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || (attrs.id || {}).value === m[2]) &&\n\t\t\t(!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tquick: selector && quickParse( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t ( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\told = null;\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\tspecial = jQuery.event.special[ event.type ] || {},\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n\t\t\t// Pregenerate a single jQuery object for reuse with .is()\n\t\t\tjqcur = jQuery(this);\n\t\t\tjqcur.context = this.ownerDocument || this;\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process events on disabled elements (#6911, #8165)\n\t\t\t\tif ( cur.disabled !== true ) {\n\t\t\t\t\tselMatch = {};\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tjqcur[0] = cur;\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\t\tselMatch[ sel ] = (\n\t\t\t\t\t\t\t\thandleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\tret;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\t\t\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\telem._change_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) { // && selector != null\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( var type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\n\t\t\tparts.push( m[1] );\n\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\t\t/* falls through */\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n// Expose origPOS\n// \"global\" as in regardless of relation to brackets/parens\nExpr.match.globalPOS = origPOS;\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry {\n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.globalPOS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\tPOS.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery.clean(arguments) );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tnull;\n\t\t\t}\n\n\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, function( i, elem ) {\n\t\t\t\t\tif ( elem.src ) {\n\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\turl: elem.src,\n\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\tdataType: \"script\"\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\n\t// IE blanks contents when cloning scripts\n\t} else if ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdest.text = src.text;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n\n\t// Clear flags for bubbling special change/submit events, they must\n\t// be reattached when the newly cloned events are first activated\n\tdest.removeAttribute( \"_submit_attached\" );\n\tdest.removeAttribute( \"_change_attached\" );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n\t// Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n\tvar div = document.createElement( \"div\" );\n\tsafeFragment.appendChild( div );\n\n\tdiv.innerHTML = elem.outerHTML;\n\treturn div.firstChild;\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t\tclone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ?\n\t\t\t\telem.cloneNode( true ) :\n\t\t\t\tshimCloneNode( elem );\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType, script, j,\n\t\t\t\tret = [];\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\"),\n\t\t\t\t\t\tsafeChildNodes = safeFragment.childNodes,\n\t\t\t\t\t\tremove;\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\n\t\t\t\t\t// Clear elements from DocumentFragment (safeFragment or otherwise)\n\t\t\t\t\t// to avoid hoarding elements. Fixes #11356\n\t\t\t\t\tif ( div ) {\n\t\t\t\t\t\tdiv.parentNode.removeChild( div );\n\n\t\t\t\t\t\t// Guard against -1 index exceptions in FF3.6\n\t\t\t\t\t\tif ( safeChildNodes.length > 0 ) {\n\t\t\t\t\t\t\tremove = safeChildNodes[ safeChildNodes.length - 1 ];\n\n\t\t\t\t\t\t\tif ( remove && remove.parentNode ) {\n\t\t\t\t\t\t\t\tremove.parentNode.removeChild( remove );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tscript = ret[i];\n\t\t\t\tif ( scripts && jQuery.nodeName( script, \"script\" ) && (!script.type || rscriptType.test( script.type )) ) {\n\t\t\t\t\tscripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( script.nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( script.getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( script );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnum = /^[\\-+]?(?:\\d*\\.)?\\d+$/i,\n\trnumnonpx = /^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\trmargin = /^margin/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\n\t// order is important!\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\treturn jQuery.access( this, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t}, name, value, arguments.length > 1 );\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {},\n\t\t\tret, name;\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// DEPRECATED in 1.3, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle, width,\n\t\t\tstyle = elem.style;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( (defaultView = elem.ownerDocument.defaultView) &&\n\t\t\t\t(computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// WebKit uses \"computed value (percentage if specified)\" instead of \"used value\" for margins\n\t\t// which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {\n\t\t\twidth = style.width;\n\t\t\tstyle.width = ret;\n\t\t\tret = computedStyle.width;\n\t\t\tstyle.width = width;\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( rnumnonpx.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\ti = name === \"width\" ? 1 : 0,\n\t\tlen = 4;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tfor ( ; i < len; i += 2 ) {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ];\n\t}\n\n\t// Computed unit is not pixels. Stop here and return.\n\tif ( rnumnonpx.test(val) ) {\n\t\treturn val;\n\t}\n\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tfor ( ; i < len; i += 2 ) {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val + \"px\";\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\treturn jQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\treturn rnum.test( value ) ?\n\t\t\t\tvalue + \"px\" :\n\t\t\t\tvalue;\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\treturn curCSS( elem, \"margin-right\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i,\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n\t\t\t\texpanded = {};\n\n\t\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n});\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = ( typeof s.data === \"string\" ) && /^application\\/x\\-www\\-form\\-urlencoded/.test( s.contentType );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t} catch( _ ) {\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( (display === \"\" && jQuery.css(elem, \"display\") === \"none\") ||\n\t\t\t\t\t\t!jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e, hooks, replace,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\t// first pass over propertys to expand / normalize\n\t\t\tfor ( p in prop ) {\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tif ( ( hooks = jQuery.cssHooks[ name ] ) && \"expand\" in hooks ) {\n\t\t\t\t\treplace = hooks.expand( prop[ name ] );\n\t\t\t\t\tdelete prop[ name ];\n\n\t\t\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t\t\t// also - reusing 'p' from above because we have the correct \"name\"\n\t\t\t\t\tfor ( p in replace ) {\n\t\t\t\t\t\tif ( ! ( p in prop ) ) {\n\t\t\t\t\t\t\tprop[ p ] = replace[ p ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( name in prop ) {\n\t\t\t\tval = prop[ name ];\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, index ) {\n\t\t\t\tvar hooks = data[ index ];\n\t\t\t\tjQuery.removeData( elem, index, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n\t\t\t\tstopQueue( this, data, index );\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ index ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ index ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p ) {\n\t\t\treturn p;\n\t\t},\n\t\tswing: function( p ) {\n\t\t\treturn ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tif ( self.options.hide ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t\t} else if ( self.options.show ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.end );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Ensure props that can't be negative don't go there on undershoot easing\njQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {\n\t// exclude marginTop, marginLeft, marginBottom and marginRight from this list\n\tif ( prop.indexOf( \"margin\" ) ) {\n\t\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( jQuery.support.boxModel ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar getOffset,\n\trtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tgetOffset = function( elem, doc, docElem, box ) {\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow( doc ),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tgetOffset = function( elem, doc, docElem ) {\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar elem = this[0],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn null;\n\t}\n\n\tif ( elem === doc.body ) {\n\t\treturn jQuery.offset.bodyOffset( elem );\n\t}\n\n\treturn getOffset( elem, doc, doc.documentElement );\n};\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t top ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tvar clientProp = \"client\" + name,\n\t\tscrollProp = \"scroll\" + name,\n\t\toffsetProp = \"offset\" + name;\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( value ) {\n\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\tvar doc, docElemProp, orig, ret;\n\n\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\t\tdoc = elem.document;\n\t\t\t\tdocElemProp = doc.documentElement[ clientProp ];\n\t\t\t\treturn jQuery.support.boxModel && docElemProp ||\n\t\t\t\t\tdoc.body && doc.body[ clientProp ] || docElemProp;\n\t\t\t}\n\n\t\t\t// Get document width or height\n\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t// when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]\n\t\t\t\t// so we can't use max, as it'll choose the incorrect offset[Width/Height]\n\t\t\t\t// instead we use the correct client[Width/Height]\n\t\t\t\t// support:IE6\n\t\t\t\tif ( doc[ clientProp ] >= doc[ scrollProp ] ) {\n\t\t\t\t\treturn doc[ clientProp ];\n\t\t\t\t}\n\n\t\t\t\treturn Math.max(\n\t\t\t\t\telem.body[ scrollProp ], doc[ scrollProp ],\n\t\t\t\t\telem.body[ offsetProp ], doc[ offsetProp ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get width or height on the element\n\t\t\tif ( value === undefined ) {\n\t\t\t\torig = jQuery.css( elem, type );\n\t\t\t\tret = parseFloat( orig );\n\t\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\t\t\t}\n\n\t\t\t// Set the width or height on the element\n\t\t\tjQuery( elem ).css( type, value );\n\t\t}, type, value, arguments.length, null );\n\t};\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );\n/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document){\n  var _jQuery = window.jQuery.noConflict(true);\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n\n/**\n * Setup file for the Scenario.\n * Must be first in the compilation/bootstrap list.\n */\n\n// Public namespace\nangular.scenario = angular.scenario || {};\n\n/**\n * Defines a new output format.\n *\n * @param {string} name the name of the new output format\n * @param {function()} fn function(context, runner) that generates the output\n */\nangular.scenario.output = angular.scenario.output || function(name, fn) {\n  angular.scenario.output[name] = fn;\n};\n\n/**\n * Defines a new DSL statement. If your factory function returns a Future\n * it's returned, otherwise the result is assumed to be a map of functions\n * for chaining. Chained functions are subject to the same rules.\n *\n * Note: All functions on the chain are bound to the chain scope so values\n *   set on \"this\" in your statement function are available in the chained\n *   functions.\n *\n * @param {string} name The name of the statement\n * @param {function()} fn Factory function(), return a function for\n *  the statement.\n */\nangular.scenario.dsl = angular.scenario.dsl || function(name, fn) {\n  angular.scenario.dsl[name] = function() {\n    function executeStatement(statement, args) {\n      var result = statement.apply(this, args);\n      if (angular.isFunction(result) || result instanceof angular.scenario.Future)\n        return result;\n      var self = this;\n      var chain = angular.extend({}, result);\n      angular.forEach(chain, function(value, name) {\n        if (angular.isFunction(value)) {\n          chain[name] = function() {\n            return executeStatement.call(self, value, arguments);\n          };\n        } else {\n          chain[name] = value;\n        }\n      });\n      return chain;\n    }\n    var statement = fn.apply(this, arguments);\n    return function() {\n      return executeStatement.call(this, statement, arguments);\n    };\n  };\n};\n\n/**\n * Defines a new matcher for use with the expects() statement. The value\n * this.actual (like in Jasmine) is available in your matcher to compare\n * against. Your function should return a boolean. The future is automatically\n * created for you.\n *\n * @param {string} name The name of the matcher\n * @param {function()} fn The matching function(expected).\n */\nangular.scenario.matcher = angular.scenario.matcher || function(name, fn) {\n  angular.scenario.matcher[name] = function(expected) {\n    var prefix = 'expect ' + this.future.name + ' ';\n    if (this.inverse) {\n      prefix += 'not ';\n    }\n    var self = this;\n    this.addFuture(prefix + name + ' ' + angular.toJson(expected),\n      function(done) {\n        var error;\n        self.actual = self.future.value;\n        if ((self.inverse && fn.call(self, expected)) ||\n            (!self.inverse && !fn.call(self, expected))) {\n          error = 'expected ' + angular.toJson(expected) +\n            ' but was ' + angular.toJson(self.actual);\n        }\n        done(error);\n    });\n  };\n};\n\n/**\n * Initialize the scenario runner and run !\n *\n * Access global window and document object\n * Access $runner through closure\n *\n * @param {Object=} config Config options\n */\nangular.scenario.setUpAndRun = function(config) {\n  var href = window.location.href;\n  var body = _jQuery(document.body);\n  var output = [];\n  var objModel = new angular.scenario.ObjectModel($runner);\n\n  if (config && config.scenario_output) {\n    output = config.scenario_output.split(',');\n  }\n\n  angular.forEach(angular.scenario.output, function(fn, name) {\n    if (!output.length || indexOf(output,name) != -1) {\n      var context = body.append('<div></div>').find('div:last');\n      context.attr('id', name);\n      fn.call({}, context, $runner, objModel);\n    }\n  });\n\n  if (!/^http/.test(href) && !/^https/.test(href)) {\n    body.append('<p id=\"system-error\"></p>');\n    body.find('#system-error').text(\n      'Scenario runner must be run using http or https. The protocol ' +\n      href.split(':')[0] + ':// is not supported.'\n    );\n    return;\n  }\n\n  var appFrame = body.append('<div id=\"application\"></div>').find('#application');\n  var application = new angular.scenario.Application(appFrame);\n\n  $runner.on('RunnerEnd', function() {\n    appFrame.css('display', 'none');\n    appFrame.find('iframe').attr('src', 'about:blank');\n  });\n\n  $runner.on('RunnerError', function(error) {\n    if (window.console) {\n      console.log(formatException(error));\n    } else {\n      // Do something for IE\n      alert(error);\n    }\n  });\n\n  $runner.run(application);\n};\n\n/**\n * Iterates through list with iterator function that must call the\n * continueFunction to continute iterating.\n *\n * @param {Array} list list to iterate over\n * @param {function()} iterator Callback function(value, continueFunction)\n * @param {function()} done Callback function(error, result) called when\n *   iteration finishes or an error occurs.\n */\nfunction asyncForEach(list, iterator, done) {\n  var i = 0;\n  function loop(error, index) {\n    if (index && index > i) {\n      i = index;\n    }\n    if (error || i >= list.length) {\n      done(error);\n    } else {\n      try {\n        iterator(list[i++], loop);\n      } catch (e) {\n        done(e);\n      }\n    }\n  }\n  loop();\n}\n\n/**\n * Formats an exception into a string with the stack trace, but limits\n * to a specific line length.\n *\n * @param {Object} error The exception to format, can be anything throwable\n * @param {Number=} [maxStackLines=5] max lines of the stack trace to include\n *  default is 5.\n */\nfunction formatException(error, maxStackLines) {\n  maxStackLines = maxStackLines || 5;\n  var message = error.toString();\n  if (error.stack) {\n    var stack = error.stack.split('\\n');\n    if (stack[0].indexOf(message) === -1) {\n      maxStackLines++;\n      stack.unshift(error.message);\n    }\n    message = stack.slice(0, maxStackLines).join('\\n');\n  }\n  return message;\n}\n\n/**\n * Returns a function that gets the file name and line number from a\n * location in the stack if available based on the call site.\n *\n * Note: this returns another function because accessing .stack is very\n * expensive in Chrome.\n *\n * @param {Number} offset Number of stack lines to skip\n */\nfunction callerFile(offset) {\n  var error = new Error();\n\n  return function() {\n    var line = (error.stack || '').split('\\n')[offset];\n\n    // Clean up the stack trace line\n    if (line) {\n      if (line.indexOf('@') !== -1) {\n        // Firefox\n        line = line.substring(line.indexOf('@')+1);\n      } else {\n        // Chrome\n        line = line.substring(line.indexOf('(')+1).replace(')', '');\n      }\n    }\n\n    return line || '';\n  };\n}\n\n/**\n * Triggers a browser event. Attempts to choose the right event if one is\n * not specified.\n *\n * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement\n * @param {string} type Optional event type.\n * @param {Array.<string>=} keys Optional list of pressed keys\n *        (valid values: 'alt', 'meta', 'shift', 'ctrl')\n */\nfunction browserTrigger(element, type, keys) {\n  if (element && !element.nodeName) element = element[0];\n  if (!element) return;\n  if (!type) {\n    type = {\n        'text':            'change',\n        'textarea':        'change',\n        'hidden':          'change',\n        'password':        'change',\n        'button':          'click',\n        'submit':          'click',\n        'reset':           'click',\n        'image':           'click',\n        'checkbox':        'click',\n        'radio':           'click',\n        'select-one':      'change',\n        'select-multiple': 'change'\n    }[lowercase(element.type)] || 'click';\n  }\n  if (lowercase(nodeName_(element)) == 'option') {\n    element.parentNode.value = element.value;\n    element = element.parentNode;\n    type = 'change';\n  }\n\n  keys = keys || [];\n  function pressed(key) {\n    return indexOf(keys, key) !== -1;\n  }\n\n  if (msie < 9) {\n    switch(element.type) {\n      case 'radio':\n      case 'checkbox':\n        element.checked = !element.checked;\n        break;\n    }\n    // WTF!!! Error: Unspecified error.\n    // Don't know why, but some elements when detached seem to be in inconsistent state and\n    // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)\n    // forcing the browser to compute the element position (by reading its CSS)\n    // puts the element in consistent state.\n    element.style.posLeft;\n\n    // TODO(vojta): create event objects with pressed keys to get it working on IE<9\n    var ret = element.fireEvent('on' + type);\n    if (lowercase(element.type) == 'submit') {\n      while(element) {\n        if (lowercase(element.nodeName) == 'form') {\n          element.fireEvent('onsubmit');\n          break;\n        }\n        element = element.parentNode;\n      }\n    }\n    return ret;\n  } else {\n    var evnt = document.createEvent('MouseEvents'),\n        originalPreventDefault = evnt.preventDefault,\n        iframe = _jQuery('#application iframe')[0],\n        appWindow = iframe ? iframe.contentWindow : window,\n        fakeProcessDefault = true,\n        finalProcessDefault,\n        angular = appWindow.angular || {};\n\n    // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208\n    angular['ff-684208-preventDefault'] = false;\n    evnt.preventDefault = function() {\n      fakeProcessDefault = false;\n      return originalPreventDefault.apply(evnt, arguments);\n    };\n\n    evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, pressed('ctrl'), pressed('alt'),\n                        pressed('shift'), pressed('meta'), 0, element);\n\n    element.dispatchEvent(evnt);\n    finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);\n\n    delete angular['ff-684208-preventDefault'];\n\n    return finalProcessDefault;\n  }\n}\n\n/**\n * Don't use the jQuery trigger method since it works incorrectly.\n *\n * jQuery notifies listeners and then changes the state of a checkbox and\n * does not create a real browser event. A real click changes the state of\n * the checkbox and then notifies listeners.\n *\n * To work around this we instead use our own handler that fires a real event.\n */\n(function(fn){\n  var parentTrigger = fn.trigger;\n  fn.trigger = function(type) {\n    if (/(click|change|keydown|blur|input)/.test(type)) {\n      var processDefaults = [];\n      this.each(function(index, node) {\n        processDefaults.push(browserTrigger(node, type));\n      });\n\n      // this is not compatible with jQuery - we return an array of returned values,\n      // so that scenario runner know whether JS code has preventDefault() of the event or not...\n      return processDefaults;\n    }\n    return parentTrigger.apply(this, arguments);\n  };\n})(_jQuery.fn);\n\n/**\n * Finds all bindings with the substring match of name and returns an\n * array of their values.\n *\n * @param {string} bindExp The name to match\n * @return {Array.<string>} String of binding values\n */\n_jQuery.fn.bindings = function(windowJquery, bindExp) {\n  var result = [], match,\n      bindSelector = '.ng-binding:visible';\n  if (angular.isString(bindExp)) {\n    bindExp = bindExp.replace(/\\s/g, '');\n    match = function (actualExp) {\n      if (actualExp) {\n        actualExp = actualExp.replace(/\\s/g, '');\n        if (actualExp == bindExp) return true;\n        if (actualExp.indexOf(bindExp) == 0) {\n          return actualExp.charAt(bindExp.length) == '|';\n        }\n      }\n    }\n  } else if (bindExp) {\n    match = function(actualExp) {\n      return actualExp && bindExp.exec(actualExp);\n    }\n  } else {\n    match = function(actualExp) {\n      return !!actualExp;\n    };\n  }\n  var selection = this.find(bindSelector);\n  if (this.is(bindSelector)) {\n    selection = selection.add(this);\n  }\n\n  function push(value) {\n    if (value == undefined) {\n      value = '';\n    } else if (typeof value != 'string') {\n      value = angular.toJson(value);\n    }\n    result.push('' + value);\n  }\n\n  selection.each(function() {\n    var element = windowJquery(this),\n        binding;\n    if (binding = element.data('$binding')) {\n      if (typeof binding == 'string') {\n        if (match(binding)) {\n          push(element.scope().$eval(binding));\n        }\n      } else {\n        if (!angular.isArray(binding)) {\n          binding = [binding];\n        }\n        for(var fns, j=0, jj=binding.length;  j<jj; j++) {\n          fns = binding[j];\n          if (fns.parts) {\n            fns = fns.parts;\n          } else {\n            fns = [fns];\n          }\n          for (var scope, fn, i = 0, ii = fns.length; i < ii; i++) {\n            if(match((fn = fns[i]).exp)) {\n              push(fn(scope = scope || element.scope()));\n            }\n          }\n        }\n      }\n    }\n  });\n  return result;\n};\n\n/**\n * Represents the application currently being tested and abstracts usage\n * of iframes or separate windows.\n *\n * @param {Object} context jQuery wrapper around HTML context.\n */\nangular.scenario.Application = function(context) {\n  this.context = context;\n  context.append(\n    '<h2>Current URL: <a href=\"about:blank\">None</a></h2>' +\n    '<div id=\"test-frames\"></div>'\n  );\n};\n\n/**\n * Gets the jQuery collection of frames. Don't use this directly because\n * frames may go stale.\n *\n * @private\n * @return {Object} jQuery collection\n */\nangular.scenario.Application.prototype.getFrame_ = function() {\n  return this.context.find('#test-frames iframe:last');\n};\n\n/**\n * Gets the window of the test runner frame. Always favor executeAction()\n * instead of this method since it prevents you from getting a stale window.\n *\n * @private\n * @return {Object} the window of the frame\n */\nangular.scenario.Application.prototype.getWindow_ = function() {\n  var contentWindow = this.getFrame_().prop('contentWindow');\n  if (!contentWindow)\n    throw 'Frame window is not accessible.';\n  return contentWindow;\n};\n\n/**\n * Changes the location of the frame.\n *\n * @param {string} url The URL. If it begins with a # then only the\n *   hash of the page is changed.\n * @param {function()} loadFn function($window, $document) Called when frame loads.\n * @param {function()} errorFn function(error) Called if any error when loading.\n */\nangular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorFn) {\n  var self = this;\n  var frame = this.getFrame_();\n  //TODO(esprehn): Refactor to use rethrow()\n  errorFn = errorFn || function(e) { throw e; };\n  if (url === 'about:blank') {\n    errorFn('Sandbox Error: Navigating to about:blank is not allowed.');\n  } else if (url.charAt(0) === '#') {\n    url = frame.attr('src').split('#')[0] + url;\n    frame.attr('src', url);\n    this.executeAction(loadFn);\n  } else {\n    frame.remove();\n    this.context.find('#test-frames').append('<iframe>');\n    frame = this.getFrame_();\n    frame.load(function() {\n      frame.unbind();\n      try {\n        self.executeAction(loadFn);\n      } catch (e) {\n        errorFn(e);\n      }\n    }).attr('src', url);\n  }\n  this.context.find('> h2 a').attr('href', url).text(url);\n};\n\n/**\n * Executes a function in the context of the tested application. Will wait\n * for all pending angular xhr requests before executing.\n *\n * @param {function()} action The callback to execute. function($window, $document)\n *  $document is a jQuery wrapped document.\n */\nangular.scenario.Application.prototype.executeAction = function(action) {\n  var self = this;\n  var $window = this.getWindow_();\n  if (!$window.document) {\n    throw 'Sandbox Error: Application document not accessible.';\n  }\n  if (!$window.angular) {\n    return action.call(this, $window, _jQuery($window.document));\n  }\n  angularInit($window.document, function(element) {\n    var $injector = $window.angular.element(element).injector();\n    var $element = _jQuery(element);\n\n    $element.injector = function() {\n      return $injector;\n    };\n\n    $injector.invoke(function($browser){\n      $browser.notifyWhenNoOutstandingRequests(function() {\n        action.call(self, $window, $element);\n      });\n    });\n  });\n};\n\n/**\n * The representation of define blocks. Don't used directly, instead use\n * define() in your tests.\n *\n * @param {string} descName Name of the block\n * @param {Object} parent describe or undefined if the root.\n */\nangular.scenario.Describe = function(descName, parent) {\n  this.only = parent && parent.only;\n  this.beforeEachFns = [];\n  this.afterEachFns = [];\n  this.its = [];\n  this.children = [];\n  this.name = descName;\n  this.parent = parent;\n  this.id = angular.scenario.Describe.id++;\n\n  /**\n   * Calls all before functions.\n   */\n  var beforeEachFns = this.beforeEachFns;\n  this.setupBefore = function() {\n    if (parent) parent.setupBefore.call(this);\n    angular.forEach(beforeEachFns, function(fn) { fn.call(this); }, this);\n  };\n\n  /**\n   * Calls all after functions.\n   */\n  var afterEachFns = this.afterEachFns;\n  this.setupAfter  = function() {\n    angular.forEach(afterEachFns, function(fn) { fn.call(this); }, this);\n    if (parent) parent.setupAfter.call(this);\n  };\n};\n\n// Shared Unique ID generator for every describe block\nangular.scenario.Describe.id = 0;\n\n// Shared Unique ID generator for every it (spec)\nangular.scenario.Describe.specId = 0;\n\n/**\n * Defines a block to execute before each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.beforeEach = function(body) {\n  this.beforeEachFns.push(body);\n};\n\n/**\n * Defines a block to execute after each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.afterEach = function(body) {\n  this.afterEachFns.push(body);\n};\n\n/**\n * Creates a new describe block that's a child of this one.\n *\n * @param {string} name Name of the block. Appended to the parent block's name.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.describe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Same as describe() but makes ddescribe blocks the only to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.ddescribe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  child.only = true;\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Use to disable a describe block.\n */\nangular.scenario.Describe.prototype.xdescribe = angular.noop;\n\n/**\n * Defines a test.\n *\n * @param {string} name Name of the test.\n * @param {function()} vody Body of the block.\n */\nangular.scenario.Describe.prototype.it = function(name, body) {\n  this.its.push({\n    id: angular.scenario.Describe.specId++,\n    definition: this,\n    only: this.only,\n    name: name,\n    before: this.setupBefore,\n    body: body,\n    after: this.setupAfter\n  });\n};\n\n/**\n * Same as it() but makes iit tests the only test to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.iit = function(name, body) {\n  this.it.apply(this, arguments);\n  this.its[this.its.length-1].only = true;\n};\n\n/**\n * Use to disable a test block.\n */\nangular.scenario.Describe.prototype.xit = angular.noop;\n\n/**\n * Gets an array of functions representing all the tests (recursively).\n * that can be executed with SpecRunner's.\n *\n * @return {Array<Object>} Array of it blocks {\n *   definition : Object // parent Describe\n *   only: boolean\n *   name: string\n *   before: Function\n *   body: Function\n *   after: Function\n *  }\n */\nangular.scenario.Describe.prototype.getSpecs = function() {\n  var specs = arguments[0] || [];\n  angular.forEach(this.children, function(child) {\n    child.getSpecs(specs);\n  });\n  angular.forEach(this.its, function(it) {\n    specs.push(it);\n  });\n  var only = [];\n  angular.forEach(specs, function(it) {\n    if (it.only) {\n      only.push(it);\n    }\n  });\n  return (only.length && only) || specs;\n};\n\n/**\n * A future action in a spec.\n *\n * @param {string} name of the future action\n * @param {function()} future callback(error, result)\n * @param {function()} Optional. function that returns the file/line number.\n */\nangular.scenario.Future = function(name, behavior, line) {\n  this.name = name;\n  this.behavior = behavior;\n  this.fulfilled = false;\n  this.value = undefined;\n  this.parser = angular.identity;\n  this.line = line || function() { return ''; };\n};\n\n/**\n * Executes the behavior of the closure.\n *\n * @param {function()} doneFn Callback function(error, result)\n */\nangular.scenario.Future.prototype.execute = function(doneFn) {\n  var self = this;\n  this.behavior(function(error, result) {\n    self.fulfilled = true;\n    if (result) {\n      try {\n        result = self.parser(result);\n      } catch(e) {\n        error = e;\n      }\n    }\n    self.value = error || result;\n    doneFn(error, result);\n  });\n};\n\n/**\n * Configures the future to convert it's final with a function fn(value)\n *\n * @param {function()} fn function(value) that returns the parsed value\n */\nangular.scenario.Future.prototype.parsedWith = function(fn) {\n  this.parser = fn;\n  return this;\n};\n\n/**\n * Configures the future to parse it's final value from JSON\n * into objects.\n */\nangular.scenario.Future.prototype.fromJson = function() {\n  return this.parsedWith(angular.fromJson);\n};\n\n/**\n * Configures the future to convert it's final value from objects\n * into JSON.\n */\nangular.scenario.Future.prototype.toJson = function() {\n  return this.parsedWith(angular.toJson);\n};\n\n/**\n * Maintains an object tree from the runner events.\n *\n * @param {Object} runner The scenario Runner instance to connect to.\n *\n * TODO(esprehn): Every output type creates one of these, but we probably\n *  want one global shared instance. Need to handle events better too\n *  so the HTML output doesn't need to do spec model.getSpec(spec.id)\n *  silliness.\n *\n * TODO(vojta) refactor on, emit methods (from all objects) - use inheritance\n */\nangular.scenario.ObjectModel = function(runner) {\n  var self = this;\n\n  this.specMap = {};\n  this.listeners = [];\n  this.value = {\n    name: '',\n    children: {}\n  };\n\n  runner.on('SpecBegin', function(spec) {\n    var block = self.value,\n        definitions = [];\n\n    angular.forEach(self.getDefinitionPath(spec), function(def) {\n      if (!block.children[def.name]) {\n        block.children[def.name] = {\n          id: def.id,\n          name: def.name,\n          children: {},\n          specs: {}\n        };\n      }\n      block = block.children[def.name];\n      definitions.push(def.name);\n    });\n\n    var it = self.specMap[spec.id] =\n             block.specs[spec.name] =\n             new angular.scenario.ObjectModel.Spec(spec.id, spec.name, definitions);\n\n    // forward the event\n    self.emit('SpecBegin', it);\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var it = self.getSpec(spec.id);\n    it.status = 'error';\n    it.error = error;\n\n    // forward the event\n    self.emit('SpecError', it, error);\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    complete(it);\n\n    // forward the event\n    self.emit('SpecEnd', it);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var it = self.getSpec(spec.id);\n    var step = new angular.scenario.ObjectModel.Step(step.name);\n    it.steps.push(step);\n\n    // forward the event\n    self.emit('StepBegin', it, step);\n  });\n\n  runner.on('StepEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    var step = it.getLastStep();\n    if (step.name !== step.name)\n      throw 'Events fired in the wrong order. Step names don\\'t match.';\n    complete(step);\n\n    // forward the event\n    self.emit('StepEnd', it, step);\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('failure', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepFailure', it, modelStep, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('error', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepError', it, modelStep, error);\n  });\n\n  runner.on('RunnerBegin', function() {\n    self.emit('RunnerBegin');\n  });\n  runner.on('RunnerEnd', function() {\n    self.emit('RunnerEnd');\n  });\n\n  function complete(item) {\n    item.endTime = new Date().getTime();\n    item.duration = item.endTime - item.startTime;\n    item.status = item.status || 'success';\n  }\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName Name of the event to add a handler for\n * @param {function()} listener Function that will be called when event is fired\n */\nangular.scenario.ObjectModel.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.ObjectModel.prototype.emit = function(eventName) {\n  var self = this,\n      args = Array.prototype.slice.call(arguments, 1),\n      eventName = eventName.toLowerCase();\n\n  if (this.listeners[eventName]) {\n    angular.forEach(this.listeners[eventName], function(listener) {\n      listener.apply(self, args);\n    });\n  }\n};\n\n/**\n * Computes the path of definition describe blocks that wrap around\n * this spec.\n *\n * @param spec Spec to compute the path for.\n * @return {Array<Describe>} The describe block path\n */\nangular.scenario.ObjectModel.prototype.getDefinitionPath = function(spec) {\n  var path = [];\n  var currentDefinition = spec.definition;\n  while (currentDefinition && currentDefinition.name) {\n    path.unshift(currentDefinition);\n    currentDefinition = currentDefinition.parent;\n  }\n  return path;\n};\n\n/**\n * Gets a spec by id.\n *\n * @param {string} The id of the spec to get the object for.\n * @return {Object} the Spec instance\n */\nangular.scenario.ObjectModel.prototype.getSpec = function(id) {\n  return this.specMap[id];\n};\n\n/**\n * A single it block.\n *\n * @param {string} id Id of the spec\n * @param {string} name Name of the spec\n * @param {Array<string>=} definitionNames List of all describe block names that wrap this spec\n */\nangular.scenario.ObjectModel.Spec = function(id, name, definitionNames) {\n  this.id = id;\n  this.name = name;\n  this.startTime = new Date().getTime();\n  this.steps = [];\n  this.fullDefinitionName = (definitionNames || []).join(' ');\n};\n\n/**\n * Adds a new step to the Spec.\n *\n * @param {string} step Name of the step (really name of the future)\n * @return {Object} the added step\n */\nangular.scenario.ObjectModel.Spec.prototype.addStep = function(name) {\n  var step = new angular.scenario.ObjectModel.Step(name);\n  this.steps.push(step);\n  return step;\n};\n\n/**\n * Gets the most recent step.\n *\n * @return {Object} the step\n */\nangular.scenario.ObjectModel.Spec.prototype.getLastStep = function() {\n  return this.steps[this.steps.length-1];\n};\n\n/**\n * Set status of the Spec from given Step\n *\n * @param {angular.scenario.ObjectModel.Step} step\n */\nangular.scenario.ObjectModel.Spec.prototype.setStatusFromStep = function(step) {\n  if (!this.status || step.status == 'error') {\n    this.status = step.status;\n    this.error = step.error;\n    this.line = step.line;\n  }\n};\n\n/**\n * A single step inside a Spec.\n *\n * @param {string} step Name of the step\n */\nangular.scenario.ObjectModel.Step = function(name) {\n  this.name = name;\n  this.startTime = new Date().getTime();\n};\n\n/**\n * Helper method for setting all error status related properties\n *\n * @param {string} status\n * @param {string} error\n * @param {string} line\n */\nangular.scenario.ObjectModel.Step.prototype.setErrorStatus = function(status, error, line) {\n  this.status = status;\n  this.error = error;\n  this.line = line;\n};\n\n/**\n * Runner for scenarios\n *\n * Has to be initialized before any test is loaded,\n * because it publishes the API into window (global space).\n */\nangular.scenario.Runner = function($window) {\n  this.listeners = [];\n  this.$window = $window;\n  this.rootDescribe = new angular.scenario.Describe();\n  this.currentDescribe = this.rootDescribe;\n  this.api = {\n    it: this.it,\n    iit: this.iit,\n    xit: angular.noop,\n    describe: this.describe,\n    ddescribe: this.ddescribe,\n    xdescribe: angular.noop,\n    beforeEach: this.beforeEach,\n    afterEach: this.afterEach\n  };\n  angular.forEach(this.api, angular.bind(this, function(fn, key) {\n    this.$window[key] = angular.bind(this, fn);\n  }));\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.Runner.prototype.emit = function(eventName) {\n  var self = this;\n  var args = Array.prototype.slice.call(arguments, 1);\n  eventName = eventName.toLowerCase();\n  if (!this.listeners[eventName])\n    return;\n  angular.forEach(this.listeners[eventName], function(listener) {\n    listener.apply(self, args);\n  });\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName The name of the event to add a handler for\n * @param {string} listener The fn(...) that takes the extra arguments from emit()\n */\nangular.scenario.Runner.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Defines a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.describe = function(name, body) {\n  var self = this;\n  this.currentDescribe.describe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Same as describe, but makes ddescribe the only blocks to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.ddescribe = function(name, body) {\n  var self = this;\n  this.currentDescribe.ddescribe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Defines a test in a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.it = function(name, body) {\n  this.currentDescribe.it(name, body);\n};\n\n/**\n * Same as it, but makes iit tests the only tests to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.iit = function(name, body) {\n  this.currentDescribe.iit(name, body);\n};\n\n/**\n * Defines a function to be called before each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.beforeEach = function(body) {\n  this.currentDescribe.beforeEach(body);\n};\n\n/**\n * Defines a function to be called after each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.afterEach = function(body) {\n  this.currentDescribe.afterEach(body);\n};\n\n/**\n * Creates a new spec runner.\n *\n * @private\n * @param {Object} scope parent scope\n */\nangular.scenario.Runner.prototype.createSpecRunner_ = function(scope) {\n  var child = scope.$new();\n  var Cls = angular.scenario.SpecRunner;\n\n  // Export all the methods to child scope manually as now we don't mess controllers with scopes\n  // TODO(vojta): refactor scenario runner so that these objects are not tightly coupled as current\n  for (var name in Cls.prototype)\n    child[name] = angular.bind(child, Cls.prototype[name]);\n\n  Cls.call(child);\n  return child;\n};\n\n/**\n * Runs all the loaded tests with the specified runner class on the\n * provided application.\n *\n * @param {angular.scenario.Application} application App to remote control.\n */\nangular.scenario.Runner.prototype.run = function(application) {\n  var self = this;\n  var $root = angular.injector(['ng']).get('$rootScope');\n  angular.extend($root, this);\n  angular.forEach(angular.scenario.Runner.prototype, function(fn, name) {\n    $root[name] = angular.bind(self, fn);\n  });\n  $root.application = application;\n  $root.emit('RunnerBegin');\n  asyncForEach(this.rootDescribe.getSpecs(), function(spec, specDone) {\n    var dslCache = {};\n    var runner = self.createSpecRunner_($root);\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      dslCache[key] = fn.call($root);\n    });\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      self.$window[key] = function() {\n        var line = callerFile(3);\n        var scope = runner.$new();\n\n        // Make the dsl accessible on the current chain\n        scope.dsl = {};\n        angular.forEach(dslCache, function(fn, key) {\n          scope.dsl[key] = function() {\n            return dslCache[key].apply(scope, arguments);\n          };\n        });\n\n        // Make these methods work on the current chain\n        scope.addFuture = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFuture.apply(scope, arguments);\n        };\n        scope.addFutureAction = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFutureAction.apply(scope, arguments);\n        };\n\n        return scope.dsl[key].apply(scope, arguments);\n      };\n    });\n    runner.run(spec, function() {\n      runner.$destroy();\n      specDone.apply(this, arguments);\n    });\n  },\n  function(error) {\n    if (error) {\n      self.emit('RunnerError', error);\n    }\n    self.emit('RunnerEnd');\n  });\n};\n\n/**\n * This class is the \"this\" of the it/beforeEach/afterEach method.\n * Responsibilities:\n *   - \"this\" for it/beforeEach/afterEach\n *   - keep state for single it/beforeEach/afterEach execution\n *   - keep track of all of the futures to execute\n *   - run single spec (execute each future)\n */\nangular.scenario.SpecRunner = function() {\n  this.futures = [];\n  this.afterIndex = 0;\n};\n\n/**\n * Executes a spec which is an it block with associated before/after functions\n * based on the describe nesting.\n *\n * @param {Object} spec A spec object\n * @param {function()} specDone function that is called when the spec finshes. Function(error, index)\n */\nangular.scenario.SpecRunner.prototype.run = function(spec, specDone) {\n  var self = this;\n  this.spec = spec;\n\n  this.emit('SpecBegin', spec);\n\n  try {\n    spec.before.call(this);\n    spec.body.call(this);\n    this.afterIndex = this.futures.length;\n    spec.after.call(this);\n  } catch (e) {\n    this.emit('SpecError', spec, e);\n    this.emit('SpecEnd', spec);\n    specDone();\n    return;\n  }\n\n  var handleError = function(error, done) {\n    if (self.error) {\n      return done();\n    }\n    self.error = true;\n    done(null, self.afterIndex);\n  };\n\n  asyncForEach(\n    this.futures,\n    function(future, futureDone) {\n      self.step = future;\n      self.emit('StepBegin', spec, future);\n      try {\n        future.execute(function(error) {\n          if (error) {\n            self.emit('StepFailure', spec, future, error);\n            self.emit('StepEnd', spec, future);\n            return handleError(error, futureDone);\n          }\n          self.emit('StepEnd', spec, future);\n          self.$window.setTimeout(function() { futureDone(); }, 0);\n        });\n      } catch (e) {\n        self.emit('StepError', spec, future, e);\n        self.emit('StepEnd', spec, future);\n        handleError(e, futureDone);\n      }\n    },\n    function(e) {\n      if (e) {\n        self.emit('SpecError', spec, e);\n      }\n      self.emit('SpecEnd', spec);\n      // Call done in a timeout so exceptions don't recursively\n      // call this function\n      self.$window.setTimeout(function() { specDone(); }, 0);\n    }\n  );\n};\n\n/**\n * Adds a new future action.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFuture = function(name, behavior, line) {\n  var future = new angular.scenario.Future(name, angular.bind(this, behavior), line);\n  this.futures.push(future);\n  return future;\n};\n\n/**\n * Adds a new future action to be executed on the application window.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior, line) {\n  var self = this;\n  var NG = /\\[ng\\\\\\:/;\n  return this.addFuture(name, function(done) {\n    this.application.executeAction(function($window, $document) {\n\n      //TODO(esprehn): Refactor this so it doesn't need to be in here.\n      $document.elements = function(selector) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        selector = (self.selector || '') + ' ' + (selector || '');\n        selector = _jQuery.trim(selector) || '*';\n        angular.forEach(args, function(value, index) {\n          selector = selector.replace('$' + (index + 1), value);\n        });\n        var result = $document.find(selector);\n        if (selector.match(NG)) {\n          angular.forEach(['[ng-','[data-ng-','[x-ng-'], function(value, index){\n            result = result.add(selector.replace(NG, value), $document);\n          });\n        }\n        if (!result.length) {\n          throw {\n            type: 'selector',\n            message: 'Selector ' + selector + ' did not match any elements.'\n          };\n        }\n\n        return result;\n      };\n\n      try {\n        behavior.call(self, $window, $document, done);\n      } catch(e) {\n        if (e.type && e.type === 'selector') {\n          done(e.message);\n        } else {\n          throw e;\n        }\n      }\n    });\n  }, line);\n};\n\n/**\n * Shared DSL statements that are useful to all scenarios.\n */\n\n /**\n * Usage:\n *    pause() pauses until you call resume() in the console\n */\nangular.scenario.dsl('pause', function() {\n  return function() {\n    return this.addFuture('pausing for you to resume', function(done) {\n      this.emit('InteractivePause', this.spec, this.step);\n      this.$window.resume = function() { done(); };\n    });\n  };\n});\n\n/**\n * Usage:\n *    sleep(seconds) pauses the test for specified number of seconds\n */\nangular.scenario.dsl('sleep', function() {\n  return function(time) {\n    return this.addFuture('sleep for ' + time + ' seconds', function(done) {\n      this.$window.setTimeout(function() { done(null, time * 1000); }, time * 1000);\n    });\n  };\n});\n\n/**\n * Usage:\n *    browser().navigateTo(url) Loads the url into the frame\n *    browser().navigateTo(url, fn) where fn(url) is called and returns the URL to navigate to\n *    browser().reload() refresh the page (reload the same URL)\n *    browser().window.href() window.location.href\n *    browser().window.path() window.location.pathname\n *    browser().window.search() window.location.search\n *    browser().window.hash() window.location.hash without # prefix\n *    browser().location().url() see ng.$location#url\n *    browser().location().path() see ng.$location#path\n *    browser().location().search() see ng.$location#search\n *    browser().location().hash() see ng.$location#hash\n */\nangular.scenario.dsl('browser', function() {\n  var chain = {};\n\n  chain.navigateTo = function(url, delegate) {\n    var application = this.application;\n    return this.addFuture(\"browser navigate to '\" + url + \"'\", function(done) {\n      if (delegate) {\n        url = delegate.call(this, url);\n      }\n      application.navigateTo(url, function() {\n        done(null, url);\n      }, done);\n    });\n  };\n\n  chain.reload = function() {\n    var application = this.application;\n    return this.addFutureAction('browser reload', function($window, $document, done) {\n      var href = $window.location.href;\n      application.navigateTo(href, function() {\n        done(null, href);\n      }, done);\n    });\n  };\n\n  chain.window = function() {\n    var api = {};\n\n    api.href = function() {\n      return this.addFutureAction('window.location.href', function($window, $document, done) {\n        done(null, $window.location.href);\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('window.location.path', function($window, $document, done) {\n        done(null, $window.location.pathname);\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('window.location.search', function($window, $document, done) {\n        done(null, $window.location.search);\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('window.location.hash', function($window, $document, done) {\n        done(null, $window.location.hash.replace('#', ''));\n      });\n    };\n\n    return api;\n  };\n\n  chain.location = function() {\n    var api = {};\n\n    api.url = function() {\n      return this.addFutureAction('$location.url()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').url());\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('$location.path()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').path());\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('$location.search()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').search());\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('$location.hash()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').hash());\n      });\n    };\n\n    return api;\n  };\n\n  return function() {\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    expect(future).{matcher} where matcher is one of the matchers defined\n *    with angular.scenario.matcher\n *\n * ex. expect(binding(\"name\")).toEqual(\"Elliott\")\n */\nangular.scenario.dsl('expect', function() {\n  var chain = angular.extend({}, angular.scenario.matcher);\n\n  chain.not = function() {\n    this.inverse = true;\n    return chain;\n  };\n\n  return function(future) {\n    this.future = future;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    using(selector, label) scopes the next DSL element selection\n *\n * ex.\n *   using('#foo', \"'Foo' text field\").input('bar')\n */\nangular.scenario.dsl('using', function() {\n  return function(selector, label) {\n    this.selector = _jQuery.trim((this.selector||'') + ' ' + selector);\n    if (angular.isString(label) && label.length) {\n      this.label = label + ' ( ' + this.selector + ' )';\n    } else {\n      this.label = this.selector;\n    }\n    return this.dsl;\n  };\n});\n\n/**\n * Usage:\n *    binding(name) returns the value of the first matching binding\n */\nangular.scenario.dsl('binding', function() {\n  return function(name) {\n    return this.addFutureAction(\"select binding '\" + name + \"'\", function($window, $document, done) {\n      var values = $document.elements().bindings($window.angular.element, name);\n      if (!values.length) {\n        return done(\"Binding selector '\" + name + \"' did not match.\");\n      }\n      done(null, values[0]);\n    });\n  };\n});\n\n/**\n * Usage:\n *    input(name).enter(value) enters value in input with specified name\n *    input(name).check() checks checkbox\n *    input(name).select(value) selects the radio button with specified name/value\n *    input(name).val() returns the value of the input.\n */\nangular.scenario.dsl('input', function() {\n  var chain = {};\n  var supportInputEvent =  'oninput' in document.createElement('div') && msie != 9;\n\n  chain.enter = function(value, event) {\n    return this.addFutureAction(\"input '\" + this.name + \"' enter '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      input.val(value);\n      input.trigger(event || (supportInputEvent ? 'input' : 'change'));\n      done();\n    });\n  };\n\n  chain.check = function() {\n    return this.addFutureAction(\"checkbox '\" + this.name + \"' toggle\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':checkbox');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.select = function(value) {\n    return this.addFutureAction(\"radio button '\" + this.name + \"' toggle '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.\n        elements('[ng\\\\:model=\"$1\"][value=\"$2\"]', this.name, value).filter(':radio');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.val = function() {\n    return this.addFutureAction(\"return input val\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      done(null,input.val());\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n\n/**\n * Usage:\n *    repeater('#products table', 'Product List').count() number of rows\n *    repeater('#products table', 'Product List').row(1) all bindings in row as an array\n *    repeater('#products table', 'Product List').column('product.name') all values across all rows in an array\n */\nangular.scenario.dsl('repeater', function() {\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.column = function(binding) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' column '\" + binding + \"'\", function($window, $document, done) {\n      done(null, $document.elements().bindings($window.angular.element, binding));\n    });\n  };\n\n  chain.row = function(index) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' row '\" + index + \"'\", function($window, $document, done) {\n      var matches = $document.elements().slice(index, index + 1);\n      if (!matches.length)\n        return done('row ' + index + ' out of bounds');\n      done(null, matches.bindings($window.angular.element));\n    });\n  };\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    select(name).option('value') select one option\n *    select(name).options('value1', 'value2', ...) select options from a multi select\n */\nangular.scenario.dsl('select', function() {\n  var chain = {};\n\n  chain.option = function(value) {\n    return this.addFutureAction(\"select '\" + this.name + \"' option '\" + value + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[ng\\\\:model=\"$1\"]', this.name);\n      var option = select.find('option[value=\"' + value + '\"]');\n      if (option.length) {\n        select.val(value);\n      } else {\n        option = select.find('option:contains(\"' + value + '\")');\n        if (option.length) {\n          select.val(option.val());\n        }\n      }\n      select.trigger('change');\n      done();\n    });\n  };\n\n  chain.options = function() {\n    var values = arguments;\n    return this.addFutureAction(\"select '\" + this.name + \"' options '\" + values + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[multiple][ng\\\\:model=\"$1\"]', this.name);\n      select.val(values);\n      select.trigger('change');\n      done();\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    element(selector, label).count() get the number of elements that match selector\n *    element(selector, label).click() clicks an element\n *    element(selector, label).query(fn) executes fn(selectedElements, done)\n *    element(selector, label).{method}() gets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(value) sets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(key) gets the value (as defined by jQuery, ex. attr)\n *    element(selector, label).{method}(key, value) sets the value (as defined by jQuery, ex. attr)\n */\nangular.scenario.dsl('element', function() {\n  var KEY_VALUE_METHODS = ['attr', 'css', 'prop'];\n  var VALUE_METHODS = [\n    'val', 'text', 'html', 'height', 'innerHeight', 'outerHeight', 'width',\n    'innerWidth', 'outerWidth', 'position', 'scrollLeft', 'scrollTop', 'offset'\n  ];\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.click = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' click\", function($window, $document, done) {\n      var elements = $document.elements();\n      var href = elements.attr('href');\n      var eventProcessDefault = elements.trigger('click')[0];\n\n      if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {\n        this.application.navigateTo(href, function() {\n          done();\n        }, done);\n      } else {\n        done();\n      }\n    });\n  };\n\n  chain.query = function(fn) {\n    return this.addFutureAction('element ' + this.label + ' custom query', function($window, $document, done) {\n      fn.call(this, $document.elements(), done);\n    });\n  };\n\n  angular.forEach(KEY_VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(name, value) {\n      var args = arguments,\n          futureName = (args.length == 1)\n              ? \"element '\" + this.label + \"' get \" + methodName + \" '\" + name + \"'\"\n              : \"element '\" + this.label + \"' set \" + methodName + \" '\" + name + \"' to \" + \"'\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  angular.forEach(VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(value) {\n      var args = arguments,\n          futureName = (args.length == 0)\n              ? \"element '\" + this.label + \"' \" + methodName\n              : futureName = \"element '\" + this.label + \"' set \" + methodName + \" to '\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Matchers for implementing specs. Follows the Jasmine spec conventions.\n */\n\nangular.scenario.matcher('toEqual', function(expected) {\n  return angular.equals(this.actual, expected);\n});\n\nangular.scenario.matcher('toBe', function(expected) {\n  return this.actual === expected;\n});\n\nangular.scenario.matcher('toBeDefined', function() {\n  return angular.isDefined(this.actual);\n});\n\nangular.scenario.matcher('toBeTruthy', function() {\n  return this.actual;\n});\n\nangular.scenario.matcher('toBeFalsy', function() {\n  return !this.actual;\n});\n\nangular.scenario.matcher('toMatch', function(expected) {\n  return new RegExp(expected).test(this.actual);\n});\n\nangular.scenario.matcher('toBeNull', function() {\n  return this.actual === null;\n});\n\nangular.scenario.matcher('toContain', function(expected) {\n  return includes(this.actual, expected);\n});\n\nangular.scenario.matcher('toBeLessThan', function(expected) {\n  return this.actual < expected;\n});\n\nangular.scenario.matcher('toBeGreaterThan', function(expected) {\n  return this.actual > expected;\n});\n\n/**\n * User Interface for the Scenario Runner.\n *\n * TODO(esprehn): This should be refactored now that ObjectModel exists\n *  to use angular bindings for the UI.\n */\nangular.scenario.output('html', function(context, runner, model) {\n  var specUiMap = {},\n      lastStepUiMap = {};\n\n  context.append(\n    '<div id=\"header\">' +\n    '  <h1><span class=\"angular\">AngularJS</span>: Scenario Test Runner</h1>' +\n    '  <ul id=\"status-legend\" class=\"status-display\">' +\n    '    <li class=\"status-error\">0 Errors</li>' +\n    '    <li class=\"status-failure\">0 Failures</li>' +\n    '    <li class=\"status-success\">0 Passed</li>' +\n    '  </ul>' +\n    '</div>' +\n    '<div id=\"specs\">' +\n    '  <div class=\"test-children\"></div>' +\n    '</div>'\n  );\n\n  runner.on('InteractivePause', function(spec) {\n    var ui = lastStepUiMap[spec.id];\n    ui.find('.test-title').\n      html('paused... <a href=\"javascript:resume()\">resume</a> when ready.');\n  });\n\n  runner.on('SpecBegin', function(spec) {\n    var ui = findContext(spec);\n    ui.find('> .tests').append(\n      '<li class=\"status-pending test-it\"></li>'\n    );\n    ui = ui.find('> .tests li:last');\n    ui.append(\n      '<div class=\"test-info\">' +\n      '  <p class=\"test-title\">' +\n      '    <span class=\"timer-result\"></span>' +\n      '    <span class=\"test-name\"></span>' +\n      '  </p>' +\n      '</div>' +\n      '<div class=\"scrollpane\">' +\n      '  <ol class=\"test-actions\"></ol>' +\n      '</div>'\n    );\n    ui.find('> .test-info .test-name').text(spec.name);\n    ui.find('> .test-info').click(function() {\n      var scrollpane = ui.find('> .scrollpane');\n      var actions = scrollpane.find('> .test-actions');\n      var name = context.find('> .test-info .test-name');\n      if (actions.find(':visible').length) {\n        actions.hide();\n        name.removeClass('open').addClass('closed');\n      } else {\n        actions.show();\n        scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n        name.removeClass('closed').addClass('open');\n      }\n    });\n\n    specUiMap[spec.id] = ui;\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var ui = specUiMap[spec.id];\n    ui.append('<pre></pre>');\n    ui.find('> pre').text(formatException(error));\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    ui.removeClass('status-pending');\n    ui.addClass('status-' + spec.status);\n    ui.find(\"> .test-info .timer-result\").text(spec.duration + \"ms\");\n    if (spec.status === 'success') {\n      ui.find('> .test-info .test-name').addClass('closed');\n      ui.find('> .scrollpane .test-actions').hide();\n    }\n    updateTotals(spec.status);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    ui.find('> .scrollpane .test-actions').append('<li class=\"status-pending\"></li>');\n    var stepUi = lastStepUiMap[spec.id] = ui.find('> .scrollpane .test-actions li:last');\n    stepUi.append(\n      '<div class=\"timer-result\"></div>' +\n      '<div class=\"test-title\"></div>'\n    );\n    stepUi.find('> .test-title').text(step.name);\n    var scrollpane = stepUi.parents('.scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepEnd', function(spec, step) {\n    var stepUi = lastStepUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    stepUi.find('.timer-result').text(step.duration + 'ms');\n    stepUi.removeClass('status-pending');\n    stepUi.addClass('status-' + step.status);\n    var scrollpane = specUiMap[spec.id].find('> .scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  /**\n   * Finds the context of a spec block defined by the passed definition.\n   *\n   * @param {Object} The definition created by the Describe object.\n   */\n  function findContext(spec) {\n    var currentContext = context.find('#specs');\n    angular.forEach(model.getDefinitionPath(spec), function(defn) {\n      var id = 'describe-' + defn.id;\n      if (!context.find('#' + id).length) {\n        currentContext.find('> .test-children').append(\n          '<div class=\"test-describe\" id=\"' + id + '\">' +\n          '  <h2></h2>' +\n          '  <div class=\"test-children\"></div>' +\n          '  <ul class=\"tests\"></ul>' +\n          '</div>'\n        );\n        context.find('#' + id).find('> h2').text('describe: ' + defn.name);\n      }\n      currentContext = context.find('#' + id);\n    });\n    return context.find('#describe-' + spec.definition.id);\n  }\n\n  /**\n   * Updates the test counter for the status.\n   *\n   * @param {string} the status.\n   */\n  function updateTotals(status) {\n    var legend = context.find('#status-legend .status-' + status);\n    var parts = legend.text().split(' ');\n    var value = (parts[0] * 1) + 1;\n    legend.text(value + ' ' + parts[1]);\n  }\n\n  /**\n   * Add an error to a step.\n   *\n   * @param {Object} The JQuery wrapped context\n   * @param {function()} fn() that should return the file/line number of the error\n   * @param {Object} the error.\n   */\n  function addError(context, line, error) {\n    context.find('.test-title').append('<pre></pre>');\n    var message = _jQuery.trim(line() + '\\n\\n' + formatException(error));\n    context.find('.test-title pre:last').text(message);\n  }\n});\n\n/**\n * Generates JSON output into a context.\n */\nangular.scenario.output('json', function(context, runner, model) {\n  model.on('RunnerEnd', function() {\n    context.text(angular.toJson(model.value));\n  });\n});\n\n/**\n * Generates XML output into a context.\n */\nangular.scenario.output('xml', function(context, runner, model) {\n  var $ = function(args) {return new context.init(args);};\n  model.on('RunnerEnd', function() {\n    var scenario = $('<scenario></scenario>');\n    context.append(scenario);\n    serializeXml(scenario, model.value);\n  });\n\n  /**\n   * Convert the tree into XML.\n   *\n   * @param {Object} context jQuery context to add the XML to.\n   * @param {Object} tree node to serialize\n   */\n  function serializeXml(context, tree) {\n     angular.forEach(tree.children, function(child) {\n       var describeContext = $('<describe></describe>');\n       describeContext.attr('id', child.id);\n       describeContext.attr('name', child.name);\n       context.append(describeContext);\n       serializeXml(describeContext, child);\n     });\n     var its = $('<its></its>');\n     context.append(its);\n     angular.forEach(tree.specs, function(spec) {\n       var it = $('<it></it>');\n       it.attr('id', spec.id);\n       it.attr('name', spec.name);\n       it.attr('duration', spec.duration);\n       it.attr('status', spec.status);\n       its.append(it);\n       angular.forEach(spec.steps, function(step) {\n         var stepContext = $('<step></step>');\n         stepContext.attr('name', step.name);\n         stepContext.attr('duration', step.duration);\n         stepContext.attr('status', step.status);\n         it.append(stepContext);\n         if (step.error) {\n           var error = $('<error></error>');\n           stepContext.append(error);\n           error.text(formatException(stepContext.error));\n         }\n       });\n     });\n   }\n});\n\n/**\n * Creates a global value $result with the result of the runner.\n */\nangular.scenario.output('object', function(context, runner, model) {\n  runner.$window.$result = model.value;\n});\nbindJQuery();\npublishExternalAPI(angular);\n\nvar $runner = new angular.scenario.Runner(window),\n    scripts = document.getElementsByTagName('script'),\n    script = scripts[scripts.length - 1],\n    config = {};\n\nangular.forEach(script.attributes, function(attr) {\n  var match = attr.name.match(/ng[:\\-](.*)/);\n  if (match) {\n    config[match[1]] = attr.value || true;\n  }\n});\n\nif (config.autotest) {\n  JQLite(document).ready(function() {\n    angular.scenario.setUpAndRun(config);\n  });\n}\n})(window, document);\n\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n\\n[ng\\\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\\n.ng-cloak, .x-ng-cloak {\\n  display: none;\\n}\\n\\nng\\\\:form {\\n  display: block;\\n}\\n</style>');\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n/* CSS Document */\\n\\n/** Structure */\\nbody {\\n  font-family: Arial, sans-serif;\\n  margin: 0;\\n  font-size: 14px;\\n}\\n\\n#system-error {\\n  font-size: 1.5em;\\n  text-align: center;\\n}\\n\\n#json, #xml {\\n  display: none;\\n}\\n\\n#header {\\n  position: fixed;\\n  width: 100%;\\n}\\n\\n#specs {\\n  padding-top: 50px;\\n}\\n\\n#header .angular {\\n  font-family: Courier New, monospace;\\n  font-weight: bold;\\n}\\n\\n#header h1 {\\n  font-weight: normal;\\n  float: left;\\n  font-size: 30px;\\n  line-height: 30px;\\n  margin: 0;\\n  padding: 10px 10px;\\n  height: 30px;\\n}\\n\\n#application h2,\\n#specs h2 {\\n  margin: 0;\\n  padding: 0.5em;\\n  font-size: 1.1em;\\n}\\n\\n#status-legend {\\n  margin-top: 10px;\\n  margin-right: 10px;\\n}\\n\\n#header,\\n#application,\\n.test-info,\\n.test-actions li {\\n  overflow: hidden;\\n}\\n\\n#application {\\n  margin: 10px;\\n}\\n\\n#application iframe {\\n  width: 100%;\\n  height: 758px;\\n}\\n\\n#application .popout {\\n  float: right;\\n}\\n\\n#application iframe {\\n  border: none;\\n}\\n\\n.tests li,\\n.test-actions li,\\n.test-it li,\\n.test-it ol,\\n.status-display {\\n  list-style-type: none;\\n}\\n\\n.tests,\\n.test-it ol,\\n.status-display {\\n  margin: 0;\\n  padding: 0;\\n}\\n\\n.test-info {\\n  margin-left: 1em;\\n  margin-top: 0.5em;\\n  border-radius: 8px 0 0 8px;\\n  -webkit-border-radius: 8px 0 0 8px;\\n  -moz-border-radius: 8px 0 0 8px;\\n  cursor: pointer;\\n}\\n\\n.test-info:hover .test-name {\\n  text-decoration: underline;\\n}\\n\\n.test-info .closed:before {\\n  content: \\'\\\\25b8\\\\00A0\\';\\n}\\n\\n.test-info .open:before {\\n  content: \\'\\\\25be\\\\00A0\\';\\n  font-weight: bold;\\n}\\n\\n.test-it ol {\\n  margin-left: 2.5em;\\n}\\n\\n.status-display,\\n.status-display li {\\n  float: right;\\n}\\n\\n.status-display li {\\n  padding: 5px 10px;\\n}\\n\\n.timer-result,\\n.test-title {\\n  display: inline-block;\\n  margin: 0;\\n  padding: 4px;\\n}\\n\\n.test-actions .test-title,\\n.test-actions .test-result {\\n  display: table-cell;\\n  padding-left: 0.5em;\\n  padding-right: 0.5em;\\n}\\n\\n.test-actions {\\n  display: table;\\n}\\n\\n.test-actions li {\\n  display: table-row;\\n}\\n\\n.timer-result {\\n  width: 4em;\\n  padding: 0 10px;\\n  text-align: right;\\n  font-family: monospace;\\n}\\n\\n.test-it pre,\\n.test-actions pre {\\n  clear: left;\\n  color: black;\\n  margin-left: 6em;\\n}\\n\\n.test-describe {\\n  padding-bottom: 0.5em;\\n}\\n\\n.test-describe .test-describe {\\n  margin: 5px 5px 10px 2em;\\n}\\n\\n.test-actions .status-pending .test-title:before {\\n  content: \\'\\\\00bb\\\\00A0\\';\\n}\\n\\n.scrollpane {\\n   max-height: 20em;\\n   overflow: auto;\\n}\\n\\n/** Colors */\\n\\n#header {\\n  background-color: #F2C200;\\n}\\n\\n#specs h2 {\\n  border-top: 2px solid #BABAD1;\\n}\\n\\n#specs h2,\\n#application h2 {\\n  background-color: #efefef;\\n}\\n\\n#application {\\n  border: 1px solid #BABAD1;\\n}\\n\\n.test-describe .test-describe {\\n  border-left: 1px solid #BABAD1;\\n  border-right: 1px solid #BABAD1;\\n  border-bottom: 1px solid #BABAD1;\\n}\\n\\n.status-display {\\n  border: 1px solid #777;\\n}\\n\\n.status-display .status-pending,\\n.status-pending .test-info {\\n  background-color: #F9EEBC;\\n}\\n\\n.status-display .status-success,\\n.status-success .test-info {\\n  background-color: #B1D7A1;\\n}\\n\\n.status-display .status-failure,\\n.status-failure .test-info {\\n  background-color: #FF8286;\\n}\\n\\n.status-display .status-error,\\n.status-error .test-info {\\n  background-color: black;\\n  color: white;\\n}\\n\\n.test-actions .status-success .test-title {\\n  color: #30B30A;\\n}\\n\\n.test-actions .status-failure .test-title {\\n  color: #DF0000;\\n}\\n\\n.test-actions .status-error .test-title {\\n  color: black;\\n}\\n\\n.test-actions .timer-result {\\n  color: #888;\\n}\\n</style>');"
  },
  {
    "path": "chapter5/recipe1/test/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter5/recipe1/test/unit/controllersSpec.js",
    "content": "'use strict';\n\n/* jasmine specs for controllers go here */\n\ndescribe('MyCtrl', function(){\n  var scope, ctrl;\n\n  beforeEach(inject(function($injector, $controller, $rootScope) {  \n    scope = $rootScope.$new();\n    ctrl = $controller(MyCtrl, { $scope: scope });\n  }));\n\n  it('should change greeting value if name value is changed', function() {\n    scope.name = \"Frederik\";\n    scope.$digest();\n    expect(scope.greeting).toBe(\"Greetings Frederik\");\n  });\n});"
  },
  {
    "path": "chapter5/recipe2/README.md",
    "content": "# Angular Express Seed Example App\n\nBased on the [Angular Express Seed](https://github.com/btford/angular-express-seed), this simple app illustrates how to use [AngularJS](http://angularjs.org/) and [Express](http://expressjs.com/) on a [Node.js](http://nodejs.org/) server to make a simple blog."
  },
  {
    "path": "chapter5/recipe2/app.js",
    "content": "var express = require('express');\n\nvar app     = module.exports = express.createServer();\n\napp.configure(function(){\n  app.set('views', __dirname + '/views');\n  app.set('view engine', 'jade');\n  app.set('view options', {\n    layout: false\n  });\n  app.use(express.bodyParser());\n  app.use(express.methodOverride());\n  app.use(express.static(__dirname + '/public'));\n  app.use(app.router);\n});\n\napp.configure('development', function(){\n  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));\n});\n\nvar data = [\n  {\n    \"id\"   : 0,\n    \"title\": \"Lorem ipsum 1\",\n    \"text\" : \"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\"\n  },\n  {\n    \"id\"   : 1,\n    \"title\": \"Lorem ipsum 2\",\n    \"text\" : \"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\"\n  }\n];\n\napp.get('/api/posts', function (req, res) {\n  res.json(data);\n});\n\napp.get('/api/posts/:id', function (req, res) {\n  var id = req.params.id;\n  if (id >= 0 && id < data.length) {\n    data.forEach(function(post, index) {\n      if (post.id === id) return res.json(post);\n    });\n  } else {\n    res.json(false);\n  }\n});\n\napp.delete('/api/posts/:id', function (req, res) {\n  var id = req.params.id;\n  if (id >= 0 && id <= data.length) {\n    data.forEach(function(post, index) {\n      if (post.id == id) {\n        data.splice(index, 1);\n      }\n    });\n    return res.json(true);\n  } else {\n    res.json(false);\n  }\n});\n\napp.get('/', function(req, res) {\n  res.render('index');\n});\n\napp.listen(3000, function(){\n  console.log(\"Express server listening on port %d in %s mode\", app.address().port, app.settings.env);\n});\n"
  },
  {
    "path": "chapter5/recipe2/package.json",
    "content": "{\n    \"name\": \"application-name\"\n  , \"version\": \"0.0.1\"\n  , \"private\": true\n  , \"dependencies\": {\n      \"express\": \"2.5.10\"\n    , \"jade\": \">= 0.0.1\"\n  }\n}"
  },
  {
    "path": "chapter5/recipe2/public/css/app.css",
    "content": "/* app css stylesheet */\n\n.menu {\n  list-style: none;\n  border-bottom: 0.1em solid black;\n  margin-bottom: 2em;\n  padding: 0 0 0.5em;\n}\n\n.menu:before {\n  content: \"[\";\n}\n\n.menu:after {\n  content: \"]\";\n}\n\n.menu > li {\n  display: inline;\n}\n\n.menu > li:before {\n  content: \"|\";\n  padding-right: 0.3em;\n}\n\n.menu > li:nth-child(1):before {\n  content: \"\";\n  padding: 0;\n}\n"
  },
  {
    "path": "chapter5/recipe2/public/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter5/recipe2/public/js/app.js",
    "content": "'use strict';\n\n// Declare app level module which depends on filters, and services\nvar app = angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngResource']);"
  },
  {
    "path": "chapter5/recipe2/public/js/controllers.js",
    "content": "app.factory(\"Post\", function($resource) {\n  return $resource(\"/api/posts/:id\");\n});\n\napp.controller(\"PostIndexCtrl\", function($scope, Post) {\n  Post.query(function(data) {\n    $scope.posts = data;\n  });\n\n  $scope.remove = function(post) {\n    Post.remove({ id: post.id }, function() {\n      $scope.posts.forEach(function(p, index) {\n        if (p.id == post.id) $scope.posts.splice(index, 1);\n      });\n    });\n  };\n});\n\napp.controller(\"PostShowCtrl\", function($scope, Post) {\n  Post.get({ id: 1 }, function(data) {\n    $scope.post = data;\n  });\n});"
  },
  {
    "path": "chapter5/recipe2/public/js/directives.js",
    "content": "'use strict';\n\n/* Directives */\n\n\nangular.module('myApp.directives', []).\n  directive('appVersion', ['version', function(version) {\n    return function(scope, elm, attrs) {\n      elm.text(version);\n    };\n  }]);\n"
  },
  {
    "path": "chapter5/recipe2/public/js/filters.js",
    "content": "'use strict';\n\n/* Filters */\n\nangular.module('myApp.filters', []).\n  filter('interpolate', ['version', function(version) {\n    return function(text) {\n      return String(text).replace(/\\%VERSION\\%/mg, version);\n    }\n  }]);\n"
  },
  {
    "path": "chapter5/recipe2/public/js/lib/angular/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngCookies\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookies\n   * @requires $browser\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from\n   * this object, new cookies are created/deleted at the end of current $eval.\n   *\n   * @example\n   */\n   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for(name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            if (angular.isDefined(lastCookies[name])) {\n              cookies[name] = lastCookies[name];\n            } else {\n              delete cookies[name];\n            }\n          } else if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated){\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   * @example\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#get\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          return angular.fromJson($cookies[key]);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#put\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#remove\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter5/recipe2/public/js/lib/angular/angular-loader.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n\n(\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n'use strict';\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n)(window);\n\n/**\n * Closure compiler type information\n *\n * @typedef { {\n *   requires: !Array.<string>,\n *   invokeQueue: !Array.<Array.<*>>,\n *\n *   service: function(string, Function):angular.Module,\n *   factory: function(string, Function):angular.Module,\n *   value: function(string, *):angular.Module,\n *\n *   filter: function(string, Function):angular.Module,\n *\n *   init: function(Function):angular.Module\n * } }\n */\nangular.Module;\n\n"
  },
  {
    "path": "chapter5/recipe2/public/js/lib/angular/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n /**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` – {string} – The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` – {object=} – Optional set of pre-bound parameters for this action.\n *   - isArray – {boolean=} – If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n  /**\n   * We need our custom mehtod because encodeURIComponent is too aggressive and doesn't follow\n   * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n   * segments:\n   *    segment       = *pchar\n   *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n   *    pct-encoded   = \"%\" HEXDIG HEXDIG\n   *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n   *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n   *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n   */\n  function encodeUriSegment(val) {\n    return encodeUriQuery(val, true).\n      replace(/%26/gi, '&').\n      replace(/%3D/gi, '=').\n      replace(/%2B/gi, '+');\n  }\n\n\n  /**\n   * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n   * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n   * encoded per http://tools.ietf.org/html/rfc3986:\n   *    query       = *( pchar / \"/\" / \"?\" )\n   *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n   *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n   *    pct-encoded   = \"%\" HEXDIG HEXDIG\n   *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n   *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n   */\n  function encodeUriQuery(val, pctEncodeSpaces) {\n    return encodeURIComponent(val).\n      replace(/%40/gi, '@').\n      replace(/%3A/gi, ':').\n      replace(/%24/g, '$').\n      replace(/%2C/gi, ',').\n      replace((pctEncodeSpaces ? null : /%20/g), '+');\n  }\n\n  function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"/?:\" + urlParam + \"(\\\\W)\", \"g\"), '$1');\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.bind = function(additionalParamDefaults){\n          return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter5/recipe2/public/js/lib/angular/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             '<p style=\"color:blue\">an html\\n' +\n             '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n             'snippet</p>';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n          Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n           <table>\n             <tr>\n               <td>Filter</td>\n               <td>Source</td>\n               <td>Rendered</td>\n             </tr>\n             <tr id=\"html-filter\">\n               <td>html filter</td>\n               <td>\n                 <pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre>\n               </td>\n               <td>\n                 <div ng-bind-html=\"snippet\"></div>\n               </td>\n             </tr>\n             <tr id=\"escaped-html\">\n               <td>no filter</td>\n               <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind=\"snippet\"></div></td>\n             </tr>\n             <tr id=\"html-unsafe-filter\">\n               <td>unsafe html filter</td>\n               <td><pre>&lt;div ng-bind-html-unsafe=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind-html-unsafe=\"snippet\"></div></td>\n             </tr>\n           </table>\n         </div>\n     </doc:source>\n     <doc:scenario>\n       it('should sanitize the html snippet ', function() {\n         expect(using('#html-filter').element('div').html()).\n           toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n       });\n\n       it('should escape snippet without any filter', function() {\n         expect(using('#escaped-html').element('div').html()).\n           toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n                \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n                \"snippet&lt;/p&gt;\");\n       });\n\n       it('should inline raw snippet if filtered as unsafe', function() {\n         expect(using('#html-unsafe-filter').element(\"div\").html()).\n           toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n                \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n                \"snippet</p>\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new <b>text</b>');\n         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');\n         expect(using('#escaped-html').element('div').html()).toBe(\"new &lt;b&gt;text&lt;/b&gt;\");\n         expect(using('#html-unsafe-filter').binding(\"snippet\")).toBe('new <b>text</b>');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar $sanitize = function(html) {\n  var buf = [];\n    htmlParser(html, htmlSanitizeWriter(buf));\n    return buf.join('');\n};\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP = /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  URI_REGEXP = /^((ftp|https?):\\/\\/|mailto:|#)/,\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g; // Match everything outside of normal chars and \" (quote character)\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,aside,\" +\n        \"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,\" +\n        \"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,bdi,bdo,\" +\n        \"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,\" +\n        \"span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        index = html.indexOf(\"-->\");\n\n        if ( index >= 0 ) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'), function(all, text){\n        text = text.\n          replace(COMMENT_REGEXP, \"$1\").\n          replace(CDATA_REGEXP, \"$1\");\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n\n        return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw \"Parse Error: \" + html;\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {\n      var value = doubleQuotedValue\n        || singleQoutedValue\n        || unqoutedValue\n        || '';\n\n      attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nvar hiddenPre=document.createElement(\"pre\");\nfunction decodeEntities(value) {\n  hiddenPre.innerHTML=value.replace(/</g,\"&lt;\");\n  return hiddenPre.innerText || hiddenPre.textContent || '';\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] == true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] == true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).value('$sanitize', $sanitize);\n\n/**\n * @ngdoc directive\n * @name ngSanitize.directive:ngBindHtml\n *\n * @description\n * Creates a binding that will sanitize the result of evaluating the `expression` with the\n * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n */\nangular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);\n    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {\n      value = $sanitize(value);\n      element.html(value || '');\n    });\n  };\n}]);\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n *   plain email address links.\n *\n * @param {string} text Input text.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should linkify the snippet with urls', function() {\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('Pretty text with some links:&#10;' +\n                '<a href=\"http://angularjs.org/\">http://angularjs.org/</a>,&#10;' +\n                '<a href=\"mailto:us@somewhere.org\">us@somewhere.org</a>,&#10;' +\n                '<a href=\"mailto:another@somewhere.org\">another@somewhere.org</a>,&#10;' +\n                'and one more: <a href=\"ftp://127.0.0.1/\">ftp://127.0.0.1/</a>.');\n       });\n\n       it ('should not linkify snippet without the linky filter', function() {\n         expect(using('#escaped-html').binding('snippet')).\n           toBe(\"Pretty text with some links:\\n\" +\n                \"http://angularjs.org/,\\n\" +\n                \"mailto:us@somewhere.org,\\n\" +\n                \"another@somewhere.org,\\n\" +\n                \"and one more: ftp://127.0.0.1/.\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new http://link.');\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('new <a href=\"http://link\">http://link</a>.');\n         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', function() {\n  var LINKY_URL_REGEXP = /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s\\.\\;\\,\\(\\)\\{\\}\\<\\>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    // TODO(vojta): use $sanitize instead\n    var writer = htmlSanitizeWriter(html);\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      writer.chars(raw.substr(0, i));\n      writer.start('a', {href:url});\n      writer.chars(match[0].replace(MAILTO_REGEXP, ''));\n      writer.end('a');\n      raw = raw.substring(i + match[0].length);\n    }\n    writer.chars(raw);\n    return html.join('');\n  };\n});\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter5/recipe2/public/js/lib/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) !== '$' && !isFunction(o1[key]) && !equals(o1[key], o2[key])) {\n            return false;\n          }\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] && key.charAt(0) !== '$' && !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.3',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 3,\n  codeName: 'bouncy-thunder'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular privides an additional method to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeName != '#text')\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes;\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    return element.nextSibling;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key, path)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $locaiton.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n          if (lastCookies.length > 20) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because too many cookies \" +\n              \"were already set (\" + lastCookies.length + \" > 20 )\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n     var linkFns = [],\n         nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n     for(var i = 0; i < nodeList.length; i++) {\n       attrs = new Attributes();\n\n       // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n       directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n       nodeLinkFn = (directives.length)\n           ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n           : null;\n\n       childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n           ? null\n           : compileNodes(nodeList[i].childNodes,\n                nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n       linkFns.push(nodeLinkFn);\n       linkFns.push(childLinkFn);\n       linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n     }\n\n     // return a linking function if we have found anything, null otherwise\n     return linkFnFound ? compositeLinkFn : null;\n\n     function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n       var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn;\n\n       for(var i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n         node = nodeList[n];\n         nodeLinkFn = linkFns[i++];\n         childLinkFn = linkFns[i++];\n\n         if (nodeLinkFn) {\n           if (nodeLinkFn.scope) {\n             childScope = scope.$new(isObject(nodeLinkFn.scope));\n             jqLite(node).data('$scope', childScope);\n           } else {\n             childScope = scope;\n           }\n           childTranscludeFn = nodeLinkFn.transclude;\n           if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n             nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                 (function(transcludeFn) {\n                   return function(cloneFn) {\n                     var transcludeScope = scope.$new();\n\n                     return transcludeFn(transcludeScope, cloneFn).\n                         bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n             );\n           } else {\n             nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n           }\n         } else if (childLinkFn) {\n           childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n         }\n       }\n     }\n   }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite('<!-- ' + directiveName + ': ' + templateAttrs[directiveName]  + ' -->');\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler}\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programing what `try`, `catch` and `throw` keywords are to synchronous programing.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exacly match the\n   *    route definition.\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var matcher = switchRouteMatcher,\n        forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n      var regex = '^' + when.replace(/([\\.\\\\\\(\\)\\^\\$])/g, \"\\\\$1\") + '$',\n          params = [],\n          dst = {};\n      forEach(when.split(/\\W/), function(param) {\n        if (param) {\n          var paramRegExp = new RegExp(\":\" + param + \"([\\\\W])\");\n          if (regex.match(paramRegExp)) {\n            regex = regex.replace(paramRegExp, \"([^\\\\/]*)$1\");\n            params.push(param);\n          }\n        }\n      });\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = matcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             this.greeting = this.salutation + ' ' + this.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { counter = counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             counter = counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        if ($rootScope == this) return; // we can't remove the root node;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBacked\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with status\n     *       // code outside of the <200, 400) range\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n          return false; // Needed for opera\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containg forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `REQUIRED`, `URL` or `EMAIL`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.REQUIRED\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.REQUIRED = {{!!myForm.$error.REQUIRED}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            collectionLength = size(collection, true),\n            childScope,\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            key, value, // key/value of iteration\n            array, last,       // last object information {scope, element, index}\n            cursor = iterStartElement;     // current position of the node\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (collectionLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  compile: function(element, attr) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        cases = {};\n\n    element.data(NG_SWITCH, cases);\n    return function(scope, element){\n      var selectedTransclude,\n          selectedElement,\n          selectedScope;\n\n      scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n        if (selectedElement) {\n          selectedScope.$destroy();\n          selectedElement.remove();\n          selectedElement = selectedScope = null;\n        }\n        if ((selectedTransclude = cases['!' + value] || cases['?'])) {\n          scope.$eval(attr.change);\n          selectedScope = scope.$new();\n          selectedTransclude(selectedScope, function(caseElement) {\n            selectedElement = caseElement;\n            element.append(caseElement);\n          });\n        }\n      });\n    };\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  compile: function(element, attrs, transclude) {\n    var cases = element.inheritedData(NG_SWITCH);\n    assertArg(cases);\n    cases['!' + attrs.ngSwitchWhen] = transclude;\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  compile: function(element, attrs, transclude) {\n    var cases = element.inheritedData(NG_SWITCH);\n    assertArg(cases);\n    cases['?'] = transclude;\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.template = {{$route.current.template}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.children(), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.children(), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter5/recipe2/public/js/lib/angular/version.txt",
    "content": "1.0.3\n"
  },
  {
    "path": "chapter5/recipe2/public/js/services.js",
    "content": "'use strict';\n\n/* Services */\n\n\n// Demonstrate how to register services\n// In this case it is a simple value service.\nangular.module('myApp.services', []).\n  value('version', '0.1');\n"
  },
  {
    "path": "chapter5/recipe2/views/index.jade",
    "content": "extends layout\n\nblock body\n  div(ng-controller=\"PostIndexCtrl\")\n    h3 List of posts\n    ul\n      li(ng-repeat=\"post in posts\")\n        span {{post.title}}\n          a(ng-click=\"remove(post)\") Delete\n\n  div(ng-controller=\"PostShowCtrl\")\n    p A Single Post: {{post.title}}\n\n  script(src='js/lib/angular/angular.js')\n  script(src='js/lib/angular/angular-resource.js')\n  script(src='js/app.js')\n  script(src='js/services.js')\n  script(src='js/controllers.js')\n  script(src='js/filters.js')\n  script(src='js/directives.js')\n"
  },
  {
    "path": "chapter5/recipe2/views/layout.jade",
    "content": "!!!\nhtml(ng-app=\"myApp\")\n  head\n    meta(charset='utf8')\n    base(href='/')\n    title Angular Express Seed App\n    link(rel='stylesheet', href='/css/bootstrap.css')\n  body\n    block body"
  },
  {
    "path": "chapter5/recipe3/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter5/recipe3/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/angular-resource.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <div ng-controller=\"MyCtrl\">\n      <input type=\"text\" ng-model=\"searchTerm\" placeholder=\"Search term\">\n      <button ng-click=\"search()\">Search</button>\n      <ul ng-repeat=\"tweet in searchResult.results\">\n        <li>{{tweet.text}}</li>\n      </ul>\n    </div>  \n  </body>\n</html>\n"
  },
  {
    "path": "chapter5/recipe3/js/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g. \n *   `http://example.com:8080/api`), you'll need to escape the colon character before the port\n *   number, like this: `$resource('http://example.com\\\\:8080/api')`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` â€“ {string} â€“ The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` â€“ {string} â€“ HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` â€“ {object=} â€“ Optional set of pre-bound parameters for this action.\n *   - isArray â€“ {boolean=} â€“ If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n     * encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace((pctEncodeSpaces ? null : /%20/g), '+');\n    }\n\n    function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        action.method = angular.uppercase(action.method);\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);"
  },
  {
    "path": "chapter5/recipe3/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter5/recipe3/js/app.js",
    "content": "var app = angular.module(\"MyApp\", [\"ngResource\"]);\n\nfunction MyCtrl($scope, $resource) {\n  $scope.twitterAPI = $resource(\"http://search.twitter.com/search.json\",\n    { callback: \"JSON_CALLBACK\" },\n    { get: { method: \"JSONP\" }});\n\n  $scope.search = function() {\n    $scope.searchResult = $scope.twitterAPI.get({ q: $scope.searchTerm });\n  };\n}\n"
  },
  {
    "path": "chapter5/recipe4/README.md",
    "content": "# angular-seed — the seed for AngularJS apps\n\nThis project is an application skeleton for a typical [AngularJS](http://angularjs.org/) web app.\nYou can use it to quickly bootstrap your angular webapp projects and dev environment for these\nprojects.\n\nThe seed contains AngularJS libraries, test libraries and a bunch of scripts all preconfigured for\ninstant web development gratification. Just clone the repo (or download the zip/tarball), start up\nour (or yours) webserver and you are ready to develop and test your application.\n\nThe seed app doesn't do much, just shows how to wire two controllers and views together. You can\ncheck it out by opening app/index.html in your browser (might not work file `file://` scheme in\ncertain browsers, see note below).\n\n_Note: While angular is client-side-only technology and it's possible to create angular webapps that\ndon't require a backend server at all, we recommend hosting the project files using a local\nwebserver during development to avoid issues with security restrictions (sandbox) in browsers. The\nsandbox implementation varies between browsers, but quite often prevents things like cookies, xhr,\netc to function properly when an html page is opened via `file://` scheme instead of `http://`._\n\n\n## How to use angular-seed\n\nClone the angular-seed repository and start hacking...\n\n\n### Running the app during development\n\nYou can pick one of these options:\n\n* serve this repository with your webserver\n* install node.js and run `scripts/web-server.js`\n\nThen navigate your browser to `http://localhost:<port>/app/index.html` to see the app running in\nyour browser.\n\n\n### Running the app in production\n\nThis really depends on how complex is your app and the overall infrastructure of your system, but\nthe general rule is that all you need in production are all the files under the `app/` directory.\nEverything else should be omitted.\n\nAngular apps are really just a bunch of static html, css and js files that just need to be hosted\nsomewhere, where they can be accessed by browsers.\n\nIf your Angular app is talking to the backend server via xhr or other means, you need to figure\nout what is the best way to host the static files to comply with the same origin policy if\napplicable. Usually this is done by hosting the files by the backend server or through\nreverse-proxying the backend server(s) and a webserver(s).\n\n\n### Running unit tests\n\nWe recommend using [jasmine](http://pivotal.github.com/jasmine/) and\n[Testacular](http://vojtajina.github.com/testacular/) for your unit tests/specs, but you are free\nto use whatever works for you.\n\nRequires [node.js](http://nodejs.org/), Testacular (`sudo npm install -g testacular`) and a local\nor remote browser.\n\n* start `scripts/test.sh` (on windows: `scripts\\test.bat`)\n  * a browser will start and connect to the Testacular server (Chrome is default browser, others can be captured by loading the same url as the one in Chrome or by changing the `config/testacular.conf.js` file)\n* to run or re-run tests just change any of your source or test javascript files\n\n\n### End to end testing\n\nAngular ships with a baked-in end-to-end test runner that understands angular, your app and allows\nyou to write your tests with jasmine-like BDD syntax.\n\nRequires a webserver, node.js + `./scripts/web-server.js` or your backend server that hosts the angular static files.\n\nCheck out the\n[end-to-end runner's documentation](http://docs.angularjs.org/guide/dev_guide.e2e-testing) for more\ninfo.\n\n* create your end-to-end tests in `test/e2e/scenarios.js`\n* serve your project directory with your http/backend server or node.js + `scripts/web-server.js`\n* to run do one of:\n  * open `http://localhost:port/test/e2e/runner.html` in your browser\n  * run the tests from console with [Testacular](vojtajina.github.com/testacular) via\n    `scripts/e2e-test.sh` or `script/e2e-test.bat`\n\n\n### Receiving updates from upstream\n\nWhen we upgrade angular-seed's repo with newer angular or testing library code, you can just\nfetch the changes and merge them into your project with git.\n\n\n## Directory Layout\n\n    app/                --> all of the files to be used in production\n      css/              --> css files\n        app.css         --> default stylesheet\n      img/              --> image files\n      index.html        --> app layout file (the main html template file of the app)\n      index-async.html  --> just like index.html, but loads js files asynchronously\n      js/               --> javascript files\n        app.js          --> application\n        controllers.js  --> application controllers\n        directives.js   --> application directives\n        filters.js      --> custom angular filters\n        services.js     --> custom angular services\n      lib/              --> angular and 3rd party javascript libraries\n        angular/\n          angular.js        --> the latest angular js\n          angular.min.js    --> the latest minified angular js\n          angular-*.js      --> angular add-on modules\n          version.txt       --> version number\n      partials/             --> angular view partials (partial html templates)\n        partial1.html\n        partial2.html\n\n    config/testacular.conf.js        --> config file for running unit tests with Testacular\n    config/testacular-e2e.conf.js    --> config file for running e2e tests with Testacular\n\n    scripts/            --> handy shell/js/ruby scripts\n      e2e-test.sh       --> runs end-to-end tests with Testacular (*nix)\n      e2e-test.bat      --> runs end-to-end tests with Testacular (windows)\n      test.bat          --> autotests unit tests with Testacular (windows)\n      test.sh           --> autotests unit tests with Testacular (*nix)\n      web-server.js     --> simple development webserver based on node.js\n\n    test/               --> test source files and libraries\n      e2e/              -->\n        runner.html     --> end-to-end test runner (open in your browser to run)\n        scenarios.js    --> end-to-end specs\n      lib/\n        angular/                --> angular testing libraries\n          angular-mocks.js      --> mocks that replace certain angular services in tests\n          angular-scenario.js   --> angular's scenario (end-to-end) test runner library\n          version.txt           --> version file\n      unit/                     --> unit level specs/tests\n        controllersSpec.js      --> specs for controllers\n        directivessSpec.js      --> specs for directives\n        filtersSpec.js          --> specs for filters\n        servicesSpec.js         --> specs for services\n\n## Contact\n\nFor more information on AngularJS please check out http://angularjs.org/\n"
  },
  {
    "path": "chapter5/recipe4/app/css/.gitignore",
    "content": ""
  },
  {
    "path": "chapter5/recipe4/app/css/app.css",
    "content": "/* app css stylesheet */\n\n.menu {\n  list-style: none;\n  border-bottom: 0.1em solid black;\n  margin-bottom: 2em;\n  padding: 0 0 0.5em;\n}\n\n.menu:before {\n  content: \"[\";\n}\n\n.menu:after {\n  content: \"]\";\n}\n\n.menu > li {\n  display: inline;\n}\n\n.menu > li:before {\n  content: \"|\";\n  padding-right: 0.3em;\n}\n\n.menu > li:nth-child(1):before {\n  content: \"\";\n  padding: 0;\n}\n"
  },
  {
    "path": "chapter5/recipe4/app/data/first.json",
    "content": "[\"Peter\"]"
  },
  {
    "path": "chapter5/recipe4/app/data/second.json",
    "content": "[\"Albert\"]"
  },
  {
    "path": "chapter5/recipe4/app/data/third.json",
    "content": "[\"Diana\"]"
  },
  {
    "path": "chapter5/recipe4/app/img/.gitignore",
    "content": ""
  },
  {
    "path": "chapter5/recipe4/app/index.html",
    "content": "<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\"/>\n</head>\n<body ng-app=\"MyApp\">\n  <div ng-controller=\"MyCtrl\">\n\n    <h3>Nested $http calls Test</h3>\n    <button ng-click=\"nestedTest()\">Nested $http calls Test</button>\n    <p>Combined Result: {{combinedNestedResult}}</p>\n\n    <h3>$q.all Test</h3>\n    <button ng-click=\"allTest()\">$q.all() Test</button>\n    <p>Combined Result: {{combinedResult}}</p>\n\n    <h3>Deferred Timer Test</h3>\n    <input type=\"checkbox\" ng-model=\"success\" ng-checked=\"success\"> Toggle Success/Failure\n    <button ng-click=\"startDeferredTimer(success)\">Start Test</button>\n    <p>1 sec Timer Result: {{deferredTimerResult}}</p>\n  </div>\n\n  <script src=\"lib/angular/angular.js\"></script>\n  <script src=\"js/controllers.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "chapter5/recipe4/app/js/controllers.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.controller(\"MyCtrl\", function($scope, $q, $http, $timeout) {\n\n  $scope.nestedTest = function() {\n    tmp = [];\n\n    $http.get(\"/app/data/first.json\").success(function(data) {\n      tmp.push(data);\n      $http.get(\"/app/data/second.json\").success(function(data) {\n        tmp.push(data);\n        $http.get(\"/app/data/third.json\").success(function(data) {\n          tmp.push(data);\n          $scope.combinedNestedResult = tmp.join(\", \");\n        });\n      });\n    });\n  };\n\n  $scope.allTest = function() {\n    var first  = $http.get(\"/app/data/first.json\"),\n        second = $http.get(\"/app/data/second.json\"),\n        third  = $http.get(\"/app/data/third.json\");\n\n    $q.all([first, second, third]).then(function(result) {\n      var tmp = [];\n      angular.forEach(result, function(response) {\n        tmp.push(response.data);\n      });\n      return tmp;\n    }).then(function(result) {\n      $scope.combinedResult = result.join(\", \");\n    });\n  };\n\n  $scope.startDeferredTimer = function(success) {\n    deferredTimer(success).then(\n      function(data) {\n        $scope.deferredTimerResult = \"Successfully finished: \" + data.message;\n      },\n      function(data) {\n        $scope.deferredTimerResult = \"Failed: \" + data.message;\n      }\n    );\n  };\n\n  function deferredTimer(success) {\n    var deferred = $q.defer();\n\n    $timeout(function() {\n      if (success) {\n        deferred.resolve({ message: \"This is great!\" });\n      } else {\n        deferred.reject({ message: \"Really bad\" });\n      }\n    }, 1000);\n\n    return deferred.promise;\n  }\n\n});\n"
  },
  {
    "path": "chapter5/recipe4/app/lib/angular/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngCookies\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookies\n   * @requires $browser\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from\n   * this object, new cookies are created/deleted at the end of current $eval.\n   *\n   * @example\n   */\n   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for(name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            if (angular.isDefined(lastCookies[name])) {\n              cookies[name] = lastCookies[name];\n            } else {\n              delete cookies[name];\n            }\n          } else if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated){\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   * @example\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#get\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          return angular.fromJson($cookies[key]);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#put\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#remove\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter5/recipe4/app/lib/angular/angular-loader.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n\n(\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n'use strict';\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n)(window);\n\n/**\n * Closure compiler type information\n *\n * @typedef { {\n *   requires: !Array.<string>,\n *   invokeQueue: !Array.<Array.<*>>,\n *\n *   service: function(string, Function):angular.Module,\n *   factory: function(string, Function):angular.Module,\n *   value: function(string, *):angular.Module,\n *\n *   filter: function(string, Function):angular.Module,\n *\n *   init: function(Function):angular.Module\n * } }\n */\nangular.Module;\n\n"
  },
  {
    "path": "chapter5/recipe4/app/lib/angular/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g. \n *   `http://example.com:8080/api`), you'll need to escape the colon character before the port\n *   number, like this: `$resource('http://example.com\\\\:8080/api')`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` – {string} – The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` – {object=} – Optional set of pre-bound parameters for this action.\n *   - isArray – {boolean=} – If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n     * encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace((pctEncodeSpaces ? null : /%20/g), '+');\n    }\n\n    function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        action.method = angular.uppercase(action.method);\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter5/recipe4/app/lib/angular/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             '<p style=\"color:blue\">an html\\n' +\n             '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n             'snippet</p>';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n          Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n           <table>\n             <tr>\n               <td>Filter</td>\n               <td>Source</td>\n               <td>Rendered</td>\n             </tr>\n             <tr id=\"html-filter\">\n               <td>html filter</td>\n               <td>\n                 <pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre>\n               </td>\n               <td>\n                 <div ng-bind-html=\"snippet\"></div>\n               </td>\n             </tr>\n             <tr id=\"escaped-html\">\n               <td>no filter</td>\n               <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind=\"snippet\"></div></td>\n             </tr>\n             <tr id=\"html-unsafe-filter\">\n               <td>unsafe html filter</td>\n               <td><pre>&lt;div ng-bind-html-unsafe=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind-html-unsafe=\"snippet\"></div></td>\n             </tr>\n           </table>\n         </div>\n     </doc:source>\n     <doc:scenario>\n       it('should sanitize the html snippet ', function() {\n         expect(using('#html-filter').element('div').html()).\n           toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n       });\n\n       it('should escape snippet without any filter', function() {\n         expect(using('#escaped-html').element('div').html()).\n           toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n                \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n                \"snippet&lt;/p&gt;\");\n       });\n\n       it('should inline raw snippet if filtered as unsafe', function() {\n         expect(using('#html-unsafe-filter').element(\"div\").html()).\n           toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n                \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n                \"snippet</p>\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new <b>text</b>');\n         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');\n         expect(using('#escaped-html').element('div').html()).toBe(\"new &lt;b&gt;text&lt;/b&gt;\");\n         expect(using('#html-unsafe-filter').binding(\"snippet\")).toBe('new <b>text</b>');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar $sanitize = function(html) {\n  var buf = [];\n    htmlParser(html, htmlSanitizeWriter(buf));\n    return buf.join('');\n};\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP = /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  URI_REGEXP = /^((ftp|https?):\\/\\/|mailto:|#)/,\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g; // Match everything outside of normal chars and \" (quote character)\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,aside,\" +\n        \"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,\" +\n        \"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,bdi,bdo,\" +\n        \"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,\" +\n        \"span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        index = html.indexOf(\"-->\");\n\n        if ( index >= 0 ) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'), function(all, text){\n        text = text.\n          replace(COMMENT_REGEXP, \"$1\").\n          replace(CDATA_REGEXP, \"$1\");\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n\n        return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw \"Parse Error: \" + html;\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {\n      var value = doubleQuotedValue\n        || singleQoutedValue\n        || unqoutedValue\n        || '';\n\n      attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nvar hiddenPre=document.createElement(\"pre\");\nfunction decodeEntities(value) {\n  hiddenPre.innerHTML=value.replace(/</g,\"&lt;\");\n  return hiddenPre.innerText || hiddenPre.textContent || '';\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] == true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] == true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).value('$sanitize', $sanitize);\n\n/**\n * @ngdoc directive\n * @name ngSanitize.directive:ngBindHtml\n *\n * @description\n * Creates a binding that will sanitize the result of evaluating the `expression` with the\n * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n */\nangular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);\n    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {\n      value = $sanitize(value);\n      element.html(value || '');\n    });\n  };\n}]);\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n *   plain email address links.\n *\n * @param {string} text Input text.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should linkify the snippet with urls', function() {\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('Pretty text with some links:&#10;' +\n                '<a href=\"http://angularjs.org/\">http://angularjs.org/</a>,&#10;' +\n                '<a href=\"mailto:us@somewhere.org\">us@somewhere.org</a>,&#10;' +\n                '<a href=\"mailto:another@somewhere.org\">another@somewhere.org</a>,&#10;' +\n                'and one more: <a href=\"ftp://127.0.0.1/\">ftp://127.0.0.1/</a>.');\n       });\n\n       it ('should not linkify snippet without the linky filter', function() {\n         expect(using('#escaped-html').binding('snippet')).\n           toBe(\"Pretty text with some links:\\n\" +\n                \"http://angularjs.org/,\\n\" +\n                \"mailto:us@somewhere.org,\\n\" +\n                \"another@somewhere.org,\\n\" +\n                \"and one more: ftp://127.0.0.1/.\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new http://link.');\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('new <a href=\"http://link\">http://link</a>.');\n         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', function() {\n  var LINKY_URL_REGEXP = /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s\\.\\;\\,\\(\\)\\{\\}\\<\\>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    // TODO(vojta): use $sanitize instead\n    var writer = htmlSanitizeWriter(html);\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      writer.chars(raw.substr(0, i));\n      writer.start('a', {href:url});\n      writer.chars(match[0].replace(MAILTO_REGEXP, ''));\n      writer.end('a');\n      raw = raw.substring(i + match[0].length);\n    }\n    writer.chars(raw);\n    return html.join('');\n  };\n});\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter5/recipe4/app/lib/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter5/recipe4/app/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter5/recipe4/config/testacular-e2e.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  ANGULAR_SCENARIO,\n  ANGULAR_SCENARIO_ADAPTER,\n  'test/e2e/**/*.js'\n];\n\nautoWatch = false;\n\nbrowsers = ['Chrome'];\n\nsingleRun = true;\n\nproxies = {\n  '/': 'http://localhost:8000/'\n};\n\njunitReporter = {\n  outputFile: 'test_out/e2e.xml',\n  suite: 'e2e'\n};\n"
  },
  {
    "path": "chapter5/recipe4/config/testacular.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  JASMINE,\n  JASMINE_ADAPTER,\n  'app/lib/angular/angular.js',\n  'app/lib/angular/angular-*.js',\n  'test/lib/angular/angular-mocks.js',\n  'app/js/**/*.js',\n  'test/unit/**/*.js'\n];\n\nautoWatch = true;\n\nbrowsers = ['Chrome'];\n\njunitReporter = {\n  outputFile: 'test_out/unit.xml',\n  suite: 'unit'\n};\n"
  },
  {
    "path": "chapter5/recipe4/logs/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "chapter5/recipe4/scripts/e2e-test.bat",
    "content": "@echo off\n\nREM Windows script for running e2e tests\nREM You have to run server and capture some browser first\nREM\nREM Requirements:\nREM - NodeJS (http://nodejs.org/)\nREM - Testacular (npm install -g testacular)\n\nset BASE_DIR=%~dp0\ntestacular start \"%BASE_DIR%\\..\\config\\testacular-e2e.conf.js\" %*\n"
  },
  {
    "path": "chapter5/recipe4/scripts/e2e-test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular-e2e.conf.js $*\n"
  },
  {
    "path": "chapter5/recipe4/scripts/test.bat",
    "content": "@echo off\r\n\r\nREM Windows script for running unit tests\r\nREM You have to run server and capture some browser first\r\nREM\r\nREM Requirements:\r\nREM - NodeJS (http://nodejs.org/)\r\nREM - Testacular (npm install -g testacular)\r\n\r\nset BASE_DIR=%~dp0\r\ntestacular start \"%BASE_DIR%\\..\\config\\testacular.conf.js\" %*\r\n"
  },
  {
    "path": "chapter5/recipe4/scripts/test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular.conf.js $*\n"
  },
  {
    "path": "chapter5/recipe4/scripts/watchr.rb",
    "content": "#!/usr/bin/env watchr\n\n# config file for watchr http://github.com/mynyml/watchr\n# install: gem install watchr\n# run: watch watchr.rb\n# note: make sure that you have jstd server running (server.sh) and a browser captured\n\nlog_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log')\n\n`cd ..`\n`touch #{log_file}`\n\nputs \"String watchr... log file: #{log_file}\"\n\nwatch( '(app/js|test/unit)' )  do\n  `echo \"\\n\\ntest run started @ \\`date\\`\" > #{log_file}`\n  `scripts/test.sh &> #{log_file}`\nend\n\n"
  },
  {
    "path": "chapter5/recipe4/scripts/web-server.js",
    "content": "#!/usr/bin/env node\n\nvar util = require('util'),\n    http = require('http'),\n    fs = require('fs'),\n    url = require('url'),\n    events = require('events');\n\nvar DEFAULT_PORT = 8000;\n\nfunction main(argv) {\n  new HttpServer({\n    'GET': createServlet(StaticServlet),\n    'HEAD': createServlet(StaticServlet)\n  }).start(Number(argv[2]) || DEFAULT_PORT);\n}\n\nfunction escapeHtml(value) {\n  return value.toString().\n    replace('<', '&lt;').\n    replace('>', '&gt;').\n    replace('\"', '&quot;');\n}\n\nfunction createServlet(Class) {\n  var servlet = new Class();\n  return servlet.handleRequest.bind(servlet);\n}\n\n/**\n * An Http server implementation that uses a map of methods to decide\n * action routing.\n *\n * @param {Object} Map of method => Handler function\n */\nfunction HttpServer(handlers) {\n  this.handlers = handlers;\n  this.server = http.createServer(this.handleRequest_.bind(this));\n}\n\nHttpServer.prototype.start = function(port) {\n  this.port = port;\n  this.server.listen(port);\n  util.puts('Http Server running at http://localhost:' + port + '/');\n};\n\nHttpServer.prototype.parseUrl_ = function(urlString) {\n  var parsed = url.parse(urlString);\n  parsed.pathname = url.resolve('/', parsed.pathname);\n  return url.parse(url.format(parsed), true);\n};\n\nHttpServer.prototype.handleRequest_ = function(req, res) {\n  var logEntry = req.method + ' ' + req.url;\n  if (req.headers['user-agent']) {\n    logEntry += ' ' + req.headers['user-agent'];\n  }\n  util.puts(logEntry);\n  req.url = this.parseUrl_(req.url);\n  var handler = this.handlers[req.method];\n  if (!handler) {\n    res.writeHead(501);\n    res.end();\n  } else {\n    handler.call(this, req, res);\n  }\n};\n\n/**\n * Handles static content.\n */\nfunction StaticServlet() {}\n\nStaticServlet.MimeMap = {\n  'txt': 'text/plain',\n  'html': 'text/html',\n  'css': 'text/css',\n  'xml': 'application/xml',\n  'json': 'application/json',\n  'js': 'application/javascript',\n  'jpg': 'image/jpeg',\n  'jpeg': 'image/jpeg',\n  'gif': 'image/gif',\n  'png': 'image/png',\n  'svg': 'image/svg+xml'\n};\n\nStaticServlet.prototype.handleRequest = function(req, res) {\n  var self = this;\n  var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){\n    return String.fromCharCode(parseInt(hex, 16));\n  });\n  var parts = path.split('/');\n  if (parts[parts.length-1].charAt(0) === '.')\n    return self.sendForbidden_(req, res, path);\n  fs.stat(path, function(err, stat) {\n    if (err)\n      return self.sendMissing_(req, res, path);\n    if (stat.isDirectory())\n      return self.sendDirectory_(req, res, path);\n    return self.sendFile_(req, res, path);\n  });\n}\n\nStaticServlet.prototype.sendError_ = function(req, res, error) {\n  res.writeHead(500, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>Internal Server Error</title>\\n');\n  res.write('<h1>Internal Server Error</h1>');\n  res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');\n  util.puts('500 Internal Server Error');\n  util.puts(util.inspect(error));\n};\n\nStaticServlet.prototype.sendMissing_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(404, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>404 Not Found</title>\\n');\n  res.write('<h1>Not Found</h1>');\n  res.write(\n    '<p>The requested URL ' +\n    escapeHtml(path) +\n    ' was not found on this server.</p>'\n  );\n  res.end();\n  util.puts('404 Not Found: ' + path);\n};\n\nStaticServlet.prototype.sendForbidden_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(403, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>403 Forbidden</title>\\n');\n  res.write('<h1>Forbidden</h1>');\n  res.write(\n    '<p>You do not have permission to access ' +\n    escapeHtml(path) + ' on this server.</p>'\n  );\n  res.end();\n  util.puts('403 Forbidden: ' + path);\n};\n\nStaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {\n  res.writeHead(301, {\n      'Content-Type': 'text/html',\n      'Location': redirectUrl\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>301 Moved Permanently</title>\\n');\n  res.write('<h1>Moved Permanently</h1>');\n  res.write(\n    '<p>The document has moved <a href=\"' +\n    redirectUrl +\n    '\">here</a>.</p>'\n  );\n  res.end();\n  util.puts('301 Moved Permanently: ' + redirectUrl);\n};\n\nStaticServlet.prototype.sendFile_ = function(req, res, path) {\n  var self = this;\n  var file = fs.createReadStream(path);\n  res.writeHead(200, {\n    'Content-Type': StaticServlet.\n      MimeMap[path.split('.').pop()] || 'text/plain'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n  } else {\n    file.on('data', res.write.bind(res));\n    file.on('close', function() {\n      res.end();\n    });\n    file.on('error', function(error) {\n      self.sendError_(req, res, error);\n    });\n  }\n};\n\nStaticServlet.prototype.sendDirectory_ = function(req, res, path) {\n  var self = this;\n  if (path.match(/[^\\/]$/)) {\n    req.url.pathname += '/';\n    var redirectUrl = url.format(url.parse(url.format(req.url)));\n    return self.sendRedirect_(req, res, redirectUrl);\n  }\n  fs.readdir(path, function(err, files) {\n    if (err)\n      return self.sendError_(req, res, error);\n\n    if (!files.length)\n      return self.writeDirectoryIndex_(req, res, path, []);\n\n    var remaining = files.length;\n    files.forEach(function(fileName, index) {\n      fs.stat(path + '/' + fileName, function(err, stat) {\n        if (err)\n          return self.sendError_(req, res, err);\n        if (stat.isDirectory()) {\n          files[index] = fileName + '/';\n        }\n        if (!(--remaining))\n          return self.writeDirectoryIndex_(req, res, path, files);\n      });\n    });\n  });\n};\n\nStaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {\n  path = path.substring(1);\n  res.writeHead(200, {\n    'Content-Type': 'text/html'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n    return;\n  }\n  res.write('<!doctype html>\\n');\n  res.write('<title>' + escapeHtml(path) + '</title>\\n');\n  res.write('<style>\\n');\n  res.write('  ol { list-style-type: none; font-size: 1.2em; }\\n');\n  res.write('</style>\\n');\n  res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');\n  res.write('<ol>');\n  files.forEach(function(fileName) {\n    if (fileName.charAt(0) !== '.') {\n      res.write('<li><a href=\"' +\n        escapeHtml(fileName) + '\">' +\n        escapeHtml(fileName) + '</a></li>');\n    }\n  });\n  res.write('</ol>');\n  res.end();\n};\n\n// Must be last,\nmain(process.argv);\n"
  },
  {
    "path": "chapter5/recipe4/test/e2e/runner.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <title>End2end Test Runner</title>\n    <script src=\"../lib/angular/angular-scenario.js\" ng-autotest></script>\n    <script src=\"scenarios.js\"></script>\n  </head>\n  <body>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter5/recipe4/test/e2e/scenarios.js",
    "content": "'use strict';\n\n/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */\n\ndescribe('my app', function() {\n\n  beforeEach(function() {\n    browser().navigateTo('../../app/index.html');\n  });\n\n\n  it('should automatically redirect to /view1 when location hash/fragment is empty', function() {\n    expect(browser().location().url()).toBe(\"/view1\");\n  });\n\n\n  describe('view1', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view1');\n    });\n\n\n    it('should render view1 when user navigates to /view1', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 1/);\n    });\n\n  });\n\n\n  describe('view2', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view2');\n    });\n\n\n    it('should render view2 when user navigates to /view2', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 2/);\n    });\n\n  });\n});\n"
  },
  {
    "path": "chapter5/recipe4/test/lib/angular/angular-mocks.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n *\n * TODO(vojta): wrap whole file into closure during build\n */\n\n/**\n * @ngdoc overview\n * @name angular.mock\n * @description\n *\n * Namespace from 'angular-mocks.js' which contains testing related code.\n */\nangular.mock = {};\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ngMock.$browser\n *\n * @description\n * This service is a mock implementation of {@link ng.$browser}. It provides fake\n * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,\n * cookies, etc...\n *\n * The api of this service is the same as that of the real {@link ng.$browser $browser}, except\n * that there are several helper methods available which can be used in tests.\n */\nangular.mock.$BrowserProvider = function() {\n  this.$get = function(){\n    return new angular.mock.$Browser();\n  };\n};\n\nangular.mock.$Browser = function() {\n  var self = this;\n\n  this.isMock = true;\n  self.$$url = \"http://server/\";\n  self.$$lastUrl = self.$$url; // used by url polling fn\n  self.pollFns = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = angular.noop;\n  self.$$incOutstandingRequestCount = angular.noop;\n\n\n  // register url polling fn\n\n  self.onUrlChange = function(listener) {\n    self.pollFns.push(\n      function() {\n        if (self.$$lastUrl != self.$$url) {\n          self.$$lastUrl = self.$$url;\n          listener(self.$$url);\n        }\n      }\n    );\n\n    return listener;\n  };\n\n  self.cookieHash = {};\n  self.lastCookieHash = {};\n  self.deferredFns = [];\n  self.deferredNextId = 0;\n\n  self.defer = function(fn, delay) {\n    delay = delay || 0;\n    self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});\n    self.deferredFns.sort(function(a,b){ return a.time - b.time;});\n    return self.deferredNextId++;\n  };\n\n\n  self.defer.now = 0;\n\n\n  self.defer.cancel = function(deferId) {\n    var fnIndex;\n\n    angular.forEach(self.deferredFns, function(fn, index) {\n      if (fn.id === deferId) fnIndex = index;\n    });\n\n    if (fnIndex !== undefined) {\n      self.deferredFns.splice(fnIndex, 1);\n      return true;\n    }\n\n    return false;\n  };\n\n\n  /**\n   * @name ngMock.$browser#defer.flush\n   * @methodOf ngMock.$browser\n   *\n   * @description\n   * Flushes all pending requests and executes the defer callbacks.\n   *\n   * @param {number=} number of milliseconds to flush. See {@link #defer.now}\n   */\n  self.defer.flush = function(delay) {\n    if (angular.isDefined(delay)) {\n      self.defer.now += delay;\n    } else {\n      if (self.deferredFns.length) {\n        self.defer.now = self.deferredFns[self.deferredFns.length-1].time;\n      } else {\n        throw Error('No deferred tasks to be flushed');\n      }\n    }\n\n    while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {\n      self.deferredFns.shift().fn();\n    }\n  };\n  /**\n   * @name ngMock.$browser#defer.now\n   * @propertyOf ngMock.$browser\n   *\n   * @description\n   * Current milliseconds mock time.\n   */\n\n  self.$$baseHref = '';\n  self.baseHref = function() {\n    return this.$$baseHref;\n  };\n};\nangular.mock.$Browser.prototype = {\n\n/**\n  * @name ngMock.$browser#poll\n  * @methodOf ngMock.$browser\n  *\n  * @description\n  * run all fns in pollFns\n  */\n  poll: function poll() {\n    angular.forEach(this.pollFns, function(pollFn){\n      pollFn();\n    });\n  },\n\n  addPollFn: function(pollFn) {\n    this.pollFns.push(pollFn);\n    return pollFn;\n  },\n\n  url: function(url, replace) {\n    if (url) {\n      this.$$url = url;\n      return this;\n    }\n\n    return this.$$url;\n  },\n\n  cookies:  function(name, value) {\n    if (name) {\n      if (value == undefined) {\n        delete this.cookieHash[name];\n      } else {\n        if (angular.isString(value) &&       //strings only\n            value.length <= 4096) {          //strict cookie storage limits\n          this.cookieHash[name] = value;\n        }\n      }\n    } else {\n      if (!angular.equals(this.cookieHash, this.lastCookieHash)) {\n        this.lastCookieHash = angular.copy(this.cookieHash);\n        this.cookieHash = angular.copy(this.cookieHash);\n      }\n      return this.cookieHash;\n    }\n  },\n\n  notifyWhenNoOutstandingRequests: function(fn) {\n    fn();\n  }\n};\n\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandlerProvider\n *\n * @description\n * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed\n * into the `$exceptionHandler`.\n */\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandler\n *\n * @description\n * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed\n * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration\n * information.\n *\n *\n * <pre>\n *   describe('$exceptionHandlerProvider', function() {\n *\n *     it('should capture log messages and exceptions', function() {\n *\n *       module(function($exceptionHandlerProvider) {\n *         $exceptionHandlerProvider.mode('log');\n *       });\n *\n *       inject(function($log, $exceptionHandler, $timeout) {\n *         $timeout(function() { $log.log(1); });\n *         $timeout(function() { $log.log(2); throw 'banana peel'; });\n *         $timeout(function() { $log.log(3); });\n *         expect($exceptionHandler.errors).toEqual([]);\n *         expect($log.assertEmpty());\n *         $timeout.flush();\n *         expect($exceptionHandler.errors).toEqual(['banana peel']);\n *         expect($log.log.logs).toEqual([[1], [2], [3]]);\n *       });\n *     });\n *   });\n * </pre>\n */\n\nangular.mock.$ExceptionHandlerProvider = function() {\n  var handler;\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$exceptionHandlerProvider#mode\n   * @methodOf ngMock.$exceptionHandlerProvider\n   *\n   * @description\n   * Sets the logging mode.\n   *\n   * @param {string} mode Mode of operation, defaults to `rethrow`.\n   *\n   *   - `rethrow`: If any errors are are passed into the handler in tests, it typically\n   *                means that there is a bug in the application or test, so this mock will\n   *                make these tests fail.\n   *   - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores an\n   *            array of errors in `$exceptionHandler.errors`, to allow later assertion of them.\n   *            See {@link ngMock.$log#assertEmpty assertEmpty()} and\n   *             {@link ngMock.$log#reset reset()}\n   */\n  this.mode = function(mode) {\n    switch(mode) {\n      case 'rethrow':\n        handler = function(e) {\n          throw e;\n        };\n        break;\n      case 'log':\n        var errors = [];\n\n        handler = function(e) {\n          if (arguments.length == 1) {\n            errors.push(e);\n          } else {\n            errors.push([].slice.call(arguments, 0));\n          }\n        };\n\n        handler.errors = errors;\n        break;\n      default:\n        throw Error(\"Unknown mode '\" + mode + \"', only 'log'/'rethrow' modes are allowed!\");\n    }\n  };\n\n  this.$get = function() {\n    return handler;\n  };\n\n  this.mode('rethrow');\n};\n\n\n/**\n * @ngdoc service\n * @name ngMock.$log\n *\n * @description\n * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays\n * (one array per logging level). These arrays are exposed as `logs` property of each of the\n * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.\n *\n */\nangular.mock.$LogProvider = function() {\n\n  function concat(array1, array2, index) {\n    return array1.concat(Array.prototype.slice.call(array2, index));\n  }\n\n\n  this.$get = function () {\n    var $log = {\n      log: function() { $log.log.logs.push(concat([], arguments, 0)); },\n      warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },\n      info: function() { $log.info.logs.push(concat([], arguments, 0)); },\n      error: function() { $log.error.logs.push(concat([], arguments, 0)); }\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#reset\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Reset all of the logging arrays to empty.\n     */\n    $log.reset = function () {\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#log.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.log.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#warn.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.warn.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#info.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.info.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#error.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.error.logs = [];\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#assertEmpty\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.\n     */\n    $log.assertEmpty = function() {\n      var errors = [];\n      angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {\n        angular.forEach($log[logLevel].logs, function(log) {\n          angular.forEach(log, function (logItem) {\n            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\\n' + (logItem.stack || ''));\n          });\n        });\n      });\n      if (errors.length) {\n        errors.unshift(\"Expected $log to be empty! Either a message was logged unexpectedly, or an expected \" +\n          \"log message was not checked and removed:\");\n        errors.push('');\n        throw new Error(errors.join('\\n---------\\n'));\n      }\n    };\n\n    $log.reset();\n    return $log;\n  };\n};\n\n\n(function() {\n  var R_ISO8061_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?:\\:?(\\d\\d)(?:\\:?(\\d\\d)(?:\\.(\\d{3}))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d)))?$/;\n\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8061_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n  function int(str) {\n    return parseInt(str, 10);\n  }\n\n  function padNumber(num, digits, trim) {\n    var neg = '';\n    if (num < 0) {\n      neg =  '-';\n      num = -num;\n    }\n    num = '' + num;\n    while(num.length < digits) num = '0' + num;\n    if (trim)\n      num = num.substr(num.length - digits);\n    return neg + num;\n  }\n\n\n  /**\n   * @ngdoc object\n   * @name angular.mock.TzDate\n   * @description\n   *\n   * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.\n   *\n   * Mock of the Date type which has its timezone specified via constroctor arg.\n   *\n   * The main purpose is to create Date-like instances with timezone fixed to the specified timezone\n   * offset, so that we can test code that depends on local timezone settings without dependency on\n   * the time zone settings of the machine where the code is running.\n   *\n   * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)\n   * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*\n   *\n   * @example\n   * !!!! WARNING !!!!!\n   * This is not a complete Date object so only methods that were implemented can be called safely.\n   * To make matters worse, TzDate instances inherit stuff from Date via a prototype.\n   *\n   * We do our best to intercept calls to \"unimplemented\" methods, but since the list of methods is\n   * incomplete we might be missing some non-standard methods. This can result in errors like:\n   * \"Date.prototype.foo called on incompatible Object\".\n   *\n   * <pre>\n   * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');\n   * newYearInBratislava.getTimezoneOffset() => -60;\n   * newYearInBratislava.getFullYear() => 2010;\n   * newYearInBratislava.getMonth() => 0;\n   * newYearInBratislava.getDate() => 1;\n   * newYearInBratislava.getHours() => 0;\n   * newYearInBratislava.getMinutes() => 0;\n   * </pre>\n   *\n   */\n  angular.mock.TzDate = function (offset, timestamp) {\n    var self = new Date(0);\n    if (angular.isString(timestamp)) {\n      var tsStr = timestamp;\n\n      self.origDate = jsonStringToDate(timestamp);\n\n      timestamp = self.origDate.getTime();\n      if (isNaN(timestamp))\n        throw {\n          name: \"Illegal Argument\",\n          message: \"Arg '\" + tsStr + \"' passed into TzDate constructor is not a valid date string\"\n        };\n    } else {\n      self.origDate = new Date(timestamp);\n    }\n\n    var localOffset = new Date(timestamp).getTimezoneOffset();\n    self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;\n    self.date = new Date(timestamp + self.offsetDiff);\n\n    self.getTime = function() {\n      return self.date.getTime() - self.offsetDiff;\n    };\n\n    self.toLocaleDateString = function() {\n      return self.date.toLocaleDateString();\n    };\n\n    self.getFullYear = function() {\n      return self.date.getFullYear();\n    };\n\n    self.getMonth = function() {\n      return self.date.getMonth();\n    };\n\n    self.getDate = function() {\n      return self.date.getDate();\n    };\n\n    self.getHours = function() {\n      return self.date.getHours();\n    };\n\n    self.getMinutes = function() {\n      return self.date.getMinutes();\n    };\n\n    self.getSeconds = function() {\n      return self.date.getSeconds();\n    };\n\n    self.getTimezoneOffset = function() {\n      return offset * 60;\n    };\n\n    self.getUTCFullYear = function() {\n      return self.origDate.getUTCFullYear();\n    };\n\n    self.getUTCMonth = function() {\n      return self.origDate.getUTCMonth();\n    };\n\n    self.getUTCDate = function() {\n      return self.origDate.getUTCDate();\n    };\n\n    self.getUTCHours = function() {\n      return self.origDate.getUTCHours();\n    };\n\n    self.getUTCMinutes = function() {\n      return self.origDate.getUTCMinutes();\n    };\n\n    self.getUTCSeconds = function() {\n      return self.origDate.getUTCSeconds();\n    };\n\n    self.getUTCMilliseconds = function() {\n      return self.origDate.getUTCMilliseconds();\n    };\n\n    self.getDay = function() {\n      return self.date.getDay();\n    };\n\n    // provide this method only on browsers that already have it\n    if (self.toISOString) {\n      self.toISOString = function() {\n        return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +\n              padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +\n              padNumber(self.origDate.getUTCDate(), 2) + 'T' +\n              padNumber(self.origDate.getUTCHours(), 2) + ':' +\n              padNumber(self.origDate.getUTCMinutes(), 2) + ':' +\n              padNumber(self.origDate.getUTCSeconds(), 2) + '.' +\n              padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'\n      }\n    }\n\n    //hide all methods not implemented in this mock that the Date prototype exposes\n    var unimplementedMethods = ['getMilliseconds', 'getUTCDay',\n        'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',\n        'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',\n        'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',\n        'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',\n        'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];\n\n    angular.forEach(unimplementedMethods, function(methodName) {\n      self[methodName] = function() {\n        throw Error(\"Method '\" + methodName + \"' is not implemented in the TzDate mock\");\n      };\n    });\n\n    return self;\n  };\n\n  //make \"tzDateInstance instanceof Date\" return true\n  angular.mock.TzDate.prototype = Date.prototype;\n})();\n\n\n/**\n * @ngdoc function\n * @name angular.mock.dump\n * @description\n *\n * *NOTE*: this is not an injectable instance, just a globally available function.\n *\n * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.\n *\n * This method is also available on window, where it can be used to display objects on debug console.\n *\n * @param {*} object - any object to turn into string.\n * @return {string} a serialized string of the argument\n */\nangular.mock.dump = function(object) {\n  return serialize(object);\n\n  function serialize(object) {\n    var out;\n\n    if (angular.isElement(object)) {\n      object = angular.element(object);\n      out = angular.element('<div></div>');\n      angular.forEach(object, function(element) {\n        out.append(angular.element(element).clone());\n      });\n      out = out.html();\n    } else if (angular.isArray(object)) {\n      out = [];\n      angular.forEach(object, function(o) {\n        out.push(serialize(o));\n      });\n      out = '[ ' + out.join(', ') + ' ]';\n    } else if (angular.isObject(object)) {\n      if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {\n        out = serializeScope(object);\n      } else if (object instanceof Error) {\n        out = object.stack || ('' + object.name + ': ' + object.message);\n      } else {\n        out = angular.toJson(object, true);\n      }\n    } else {\n      out = String(object);\n    }\n\n    return out;\n  }\n\n  function serializeScope(scope, offset) {\n    offset = offset ||  '  ';\n    var log = [offset + 'Scope(' + scope.$id + '): {'];\n    for ( var key in scope ) {\n      if (scope.hasOwnProperty(key) && !key.match(/^(\\$|this)/)) {\n        log.push('  ' + key + ': ' + angular.toJson(scope[key]));\n      }\n    }\n    var child = scope.$$childHead;\n    while(child) {\n      log.push(serializeScope(child, offset + '  '));\n      child = child.$$nextSibling;\n    }\n    log.push('}');\n    return log.join('\\n' + offset);\n  }\n};\n\n/**\n * @ngdoc object\n * @name ngMock.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for unit testing application that use the\n * {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less\n * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.\n *\n * During unit testing, we want our unit tests to run quickly and have no external dependencies so\n * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or\n * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is\n * to verify whether a certain request has been sent or not, or alternatively just let the\n * application make requests, respond with pre-trained responses and assert that the end result is\n * what we expect it to be.\n *\n * This mock implementation can be used to respond with static or dynamic responses via the\n * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).\n *\n * When an Angular application needs some data from a server, it calls the $http service, which\n * sends the request to a real server using $httpBackend service. With dependency injection, it is\n * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify\n * the requests and respond with some testing data without sending a request to real server.\n *\n * There are two ways to specify what test data should be returned as http responses by the mock\n * backend when the code under test makes http requests:\n *\n * - `$httpBackend.expect` - specifies a request expectation\n * - `$httpBackend.when` - specifies a backend definition\n *\n *\n * # Request Expectations vs Backend Definitions\n *\n * Request expectations provide a way to make assertions about requests made by the application and\n * to define responses for those requests. The test will fail if the expected requests are not made\n * or they are made in the wrong order.\n *\n * Backend definitions allow you to define a fake backend for your application which doesn't assert\n * if a particular request was made or not, it just returns a trained response if a request is made.\n * The test will pass whether or not the request gets made during testing.\n *\n *\n * <table class=\"table\">\n *   <tr><th width=\"220px\"></th><th>Request expectations</th><th>Backend definitions</th></tr>\n *   <tr>\n *     <th>Syntax</th>\n *     <td>.expect(...).respond(...)</td>\n *     <td>.when(...).respond(...)</td>\n *   </tr>\n *   <tr>\n *     <th>Typical usage</th>\n *     <td>strict unit tests</td>\n *     <td>loose (black-box) unit testing</td>\n *   </tr>\n *   <tr>\n *     <th>Fulfills multiple requests</th>\n *     <td>NO</td>\n *     <td>YES</td>\n *   </tr>\n *   <tr>\n *     <th>Order of requests matters</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Request required</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Response required</th>\n *     <td>optional (see below)</td>\n *     <td>YES</td>\n *   </tr>\n * </table>\n *\n * In cases where both backend definitions and request expectations are specified during unit\n * testing, the request expectations are evaluated first.\n *\n * If a request expectation has no response specified, the algorithm will search your backend\n * definitions for an appropriate response.\n *\n * If a request didn't match any expectation or if the expectation doesn't have the response\n * defined, the backend definitions are evaluated in sequential order to see if any of them match\n * the request. The response from the first matched definition is returned.\n *\n *\n * # Flushing HTTP requests\n *\n * The $httpBackend used in production, always responds to requests with responses asynchronously.\n * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are\n * hard to write, follow and maintain. At the same time the testing mock, can't respond\n * synchronously because that would change the execution of the code under test. For this reason the\n * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending\n * requests and thus preserving the async api of the backend, while allowing the test to execute\n * synchronously.\n *\n *\n * # Unit testing with mock $httpBackend\n *\n * <pre>\n   // controller\n   function MyController($scope, $http) {\n     $http.get('/auth.py').success(function(data) {\n       $scope.user = data;\n     });\n\n     this.saveMessage = function(message) {\n       $scope.status = 'Saving...';\n       $http.post('/add-msg.py', message).success(function(response) {\n         $scope.status = '';\n       }).error(function() {\n         $scope.status = 'ERROR!';\n       });\n     };\n   }\n\n   // testing controller\n   var $httpBackend;\n\n   beforeEach(inject(function($injector) {\n     $httpBackend = $injector.get('$httpBackend');\n\n     // backend definition common for all tests\n     $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});\n   }));\n\n\n   afterEach(function() {\n     $httpBackend.verifyNoOutstandingExpectation();\n     $httpBackend.verifyNoOutstandingRequest();\n   });\n\n\n   it('should fetch authentication token', function() {\n     $httpBackend.expectGET('/auth.py');\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n   });\n\n\n   it('should send msg to server', function() {\n     // now you don’t care about the authentication, but\n     // the controller will still send the request and\n     // $httpBackend will respond without you having to\n     // specify the expectation and response for this request\n     $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');\n\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n     controller.saveMessage('message content');\n     expect(controller.status).toBe('Saving...');\n     $httpBackend.flush();\n     expect(controller.status).toBe('');\n   });\n\n\n   it('should send auth header', function() {\n     $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {\n       // check if the header was send, if it wasn't the expectation won't\n       // match the request and the test will fail\n       return headers['Authorization'] == 'xxx';\n     }).respond(201, '');\n\n     var controller = scope.$new(MyController);\n     controller.saveMessage('whatever');\n     $httpBackend.flush();\n   });\n   </pre>\n */\nangular.mock.$HttpBackendProvider = function() {\n  this.$get = [createHttpBackendMock];\n};\n\n/**\n * General factory function for $httpBackend mock.\n * Returns instance for unit testing (when no arguments specified):\n *   - passing through is disabled\n *   - auto flushing is disabled\n *\n * Returns instance for e2e testing (when `$delegate` and `$browser` specified):\n *   - passing through (delegating request to real backend) is enabled\n *   - auto flushing is enabled\n *\n * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)\n * @param {Object=} $browser Auto-flushing enabled if specified\n * @return {Object} Instance of $httpBackend mock\n */\nfunction createHttpBackendMock($delegate, $browser) {\n  var definitions = [],\n      expectations = [],\n      responses = [],\n      responsesPush = angular.bind(responses, responses.push);\n\n  function createResponse(status, data, headers) {\n    if (angular.isFunction(status)) return status;\n\n    return function() {\n      return angular.isNumber(status)\n          ? [status, data, headers]\n          : [200, status, data];\n    };\n  }\n\n  // TODO(vojta): change params to: method, url, data, headers, callback\n  function $httpBackend(method, url, data, callback, headers) {\n    var xhr = new MockXhr(),\n        expectation = expectations[0],\n        wasExpected = false;\n\n    function prettyPrint(data) {\n      return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)\n          ? data\n          : angular.toJson(data);\n    }\n\n    if (expectation && expectation.match(method, url)) {\n      if (!expectation.matchData(data))\n        throw Error('Expected ' + expectation + ' with different data\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.data) + '\\nGOT:      ' + data);\n\n      if (!expectation.matchHeaders(headers))\n        throw Error('Expected ' + expectation + ' with different headers\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.headers) + '\\nGOT:      ' +\n            prettyPrint(headers));\n\n      expectations.shift();\n\n      if (expectation.response) {\n        responses.push(function() {\n          var response = expectation.response(method, url, data, headers);\n          xhr.$$respHeaders = response[2];\n          callback(response[0], response[1], xhr.getAllResponseHeaders());\n        });\n        return;\n      }\n      wasExpected = true;\n    }\n\n    var i = -1, definition;\n    while ((definition = definitions[++i])) {\n      if (definition.match(method, url, data, headers || {})) {\n        if (definition.response) {\n          // if $browser specified, we do auto flush all requests\n          ($browser ? $browser.defer : responsesPush)(function() {\n            var response = definition.response(method, url, data, headers);\n            xhr.$$respHeaders = response[2];\n            callback(response[0], response[1], xhr.getAllResponseHeaders());\n          });\n        } else if (definition.passThrough) {\n          $delegate(method, url, data, callback, headers);\n        } else throw Error('No response defined !');\n        return;\n      }\n    }\n    throw wasExpected ?\n        Error('No response defined !') :\n        Error('Unexpected request: ' + method + ' ' + url + '\\n' +\n              (expectation ? 'Expected ' + expectation : 'No more request expected'));\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#when\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current definition.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.when = function(method, url, data, headers) {\n    var definition = new MockHttpExpectation(method, url, data, headers),\n        chain = {\n          respond: function(status, data, headers) {\n            definition.response = createResponse(status, data, headers);\n          }\n        };\n\n    if ($browser) {\n      chain.passThrough = function() {\n        definition.passThrough = true;\n      };\n    }\n\n    definitions.push(definition);\n    return chain;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for GET requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for HEAD requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for DELETE requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for POST requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for PUT requests.  For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for JSONP requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n  createShortMethods('when');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expect\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current expectation.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *  request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.expect = function(method, url, data, headers) {\n    var expectation = new MockHttpExpectation(method, url, data, headers);\n    expectations.push(expectation);\n    return {\n      respond: function(status, data, headers) {\n        expectation.response = createResponse(status, data, headers);\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for GET requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled. See #expect for more info.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for HEAD requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for DELETE requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for POST requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PUT requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPATCH\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PATCH requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for JSONP requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n  createShortMethods('expect');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#flush\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Flushes all pending requests using the trained responses.\n   *\n   * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,\n   *   all pending requests will be flushed. If there are no pending requests when the flush method\n   *   is called an exception is thrown (as this typically a sign of programming error).\n   */\n  $httpBackend.flush = function(count) {\n    if (!responses.length) throw Error('No pending request to flush !');\n\n    if (angular.isDefined(count)) {\n      while (count--) {\n        if (!responses.length) throw Error('No more pending request to flush !');\n        responses.shift()();\n      }\n    } else {\n      while (responses.length) {\n        responses.shift()();\n      }\n    }\n    $httpBackend.verifyNoOutstandingExpectation();\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingExpectation\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that all of the requests defined via the `expect` api were made. If any of the\n   * requests were not made, verifyNoOutstandingExpectation throws an exception.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyExpectations);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingExpectation = function() {\n    if (expectations.length) {\n      throw Error('Unsatisfied requests: ' + expectations.join(', '));\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingRequest\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that there are no outstanding requests that need to be flushed.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyNoOutstandingRequest);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingRequest = function() {\n    if (responses.length) {\n      throw Error('Unflushed requests: ' + responses.length);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#resetExpectations\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Resets all request expectations, but preserves all backend definitions. Typically, you would\n   * call resetExpectations during a multiple-phase test when you want to reuse the same instance of\n   * $httpBackend mock.\n   */\n  $httpBackend.resetExpectations = function() {\n    expectations.length = 0;\n    responses.length = 0;\n  };\n\n  return $httpBackend;\n\n\n  function createShortMethods(prefix) {\n    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {\n     $httpBackend[prefix + method] = function(url, headers) {\n       return $httpBackend[prefix](method, url, undefined, headers)\n     }\n    });\n\n    angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {\n      $httpBackend[prefix + method] = function(url, data, headers) {\n        return $httpBackend[prefix](method, url, data, headers)\n      }\n    });\n  }\n}\n\nfunction MockHttpExpectation(method, url, data, headers) {\n\n  this.data = data;\n  this.headers = headers;\n\n  this.match = function(m, u, d, h) {\n    if (method != m) return false;\n    if (!this.matchUrl(u)) return false;\n    if (angular.isDefined(d) && !this.matchData(d)) return false;\n    if (angular.isDefined(h) && !this.matchHeaders(h)) return false;\n    return true;\n  };\n\n  this.matchUrl = function(u) {\n    if (!url) return true;\n    if (angular.isFunction(url.test)) return url.test(u);\n    return url == u;\n  };\n\n  this.matchHeaders = function(h) {\n    if (angular.isUndefined(headers)) return true;\n    if (angular.isFunction(headers)) return headers(h);\n    return angular.equals(headers, h);\n  };\n\n  this.matchData = function(d) {\n    if (angular.isUndefined(data)) return true;\n    if (data && angular.isFunction(data.test)) return data.test(d);\n    if (data && !angular.isString(data)) return angular.toJson(data) == d;\n    return data == d;\n  };\n\n  this.toString = function() {\n    return method + ' ' + url;\n  };\n}\n\nfunction MockXhr() {\n\n  // hack for testing $http, $httpBackend\n  MockXhr.$$lastInstance = this;\n\n  this.open = function(method, url, async) {\n    this.$$method = method;\n    this.$$url = url;\n    this.$$async = async;\n    this.$$reqHeaders = {};\n    this.$$respHeaders = {};\n  };\n\n  this.send = function(data) {\n    this.$$data = data;\n  };\n\n  this.setRequestHeader = function(key, value) {\n    this.$$reqHeaders[key] = value;\n  };\n\n  this.getResponseHeader = function(name) {\n    // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last\n    var header = this.$$respHeaders[name];\n    if (header) return header;\n\n    name = angular.lowercase(name);\n    header = this.$$respHeaders[name];\n    if (header) return header;\n\n    header = undefined;\n    angular.forEach(this.$$respHeaders, function(headerVal, headerName) {\n      if (!header && angular.lowercase(headerName) == name) header = headerVal;\n    });\n    return header;\n  };\n\n  this.getAllResponseHeaders = function() {\n    var lines = [];\n\n    angular.forEach(this.$$respHeaders, function(value, key) {\n      lines.push(key + ': ' + value);\n    });\n    return lines.join('\\n');\n  };\n\n  this.abort = angular.noop;\n}\n\n\n/**\n * @ngdoc function\n * @name ngMock.$timeout\n * @description\n *\n * This service is just a simple decorator for {@link ng.$timeout $timeout} service\n * that adds a \"flush\" method.\n */\n\n/**\n * @ngdoc method\n * @name ngMock.$timeout#flush\n * @methodOf ngMock.$timeout\n * @description\n *\n * Flushes the queue of pending tasks.\n */\n\n/**\n *\n */\nangular.mock.$RootElementProvider = function() {\n  this.$get = function() {\n    return angular.element('<div ng-app></div>');\n  }\n};\n\n/**\n * @ngdoc overview\n * @name ngMock\n * @description\n *\n * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful\n * mocks to the {@link AUTO.$injector $injector}.\n */\nangular.module('ngMock', ['ng']).provider({\n  $browser: angular.mock.$BrowserProvider,\n  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,\n  $log: angular.mock.$LogProvider,\n  $httpBackend: angular.mock.$HttpBackendProvider,\n  $rootElement: angular.mock.$RootElementProvider\n}).config(function($provide) {\n  $provide.decorator('$timeout', function($delegate, $browser) {\n    $delegate.flush = function() {\n      $browser.defer.flush();\n    };\n    return $delegate;\n  });\n});\n\n\n/**\n * @ngdoc overview\n * @name ngMockE2E\n * @description\n *\n * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.\n * Currently there is only one mock present in this module -\n * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.\n */\nangular.module('ngMockE2E', ['ng']).config(function($provide) {\n  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);\n});\n\n/**\n * @ngdoc object\n * @name ngMockE2E.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of\n * applications that use the {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for unit testing please see\n * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.\n *\n * This implementation can be used to respond with static or dynamic responses via the `when` api\n * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the\n * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch\n * templates from a webserver).\n *\n * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application\n * is being developed with the real backend api replaced with a mock, it is often desirable for\n * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch\n * templates or static files from the webserver). To configure the backend with this behavior\n * use the `passThrough` request handler of `when` instead of `respond`.\n *\n * Additionally, we don't want to manually have to flush mocked out requests like we do during unit\n * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests\n * automatically, closely simulating the behavior of the XMLHttpRequest object.\n *\n * To setup the application to run with this http backend, you have to create a module that depends\n * on the `ngMockE2E` and your application modules and defines the fake backend:\n *\n * <pre>\n *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);\n *   myAppDev.run(function($httpBackend) {\n *     phones = [{name: 'phone1'}, {name: 'phone2'}];\n *\n *     // returns the current list of phones\n *     $httpBackend.whenGET('/phones').respond(phones);\n *\n *     // adds a new phone to the phones array\n *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {\n *       phones.push(angular.fromJSON(data));\n *     });\n *     $httpBackend.whenGET(/^\\/templates\\//).passThrough();\n *     //...\n *   });\n * </pre>\n *\n * Afterwards, bootstrap your app with this new module.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#when\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition.\n *\n * @param {string} method HTTP method.\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n *   object and returns true if the headers match the current definition.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n *\n *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n *    – The respond method takes a set of static data to be returned or a function that can return\n *    an array containing response status (number), response data (string) and response headers\n *    (Object).\n *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`\n *    handler, will be pass through to the real backend (an XHR request will be made to the\n *    server.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenGET\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for GET requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenHEAD\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for HEAD requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenDELETE\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for DELETE requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPOST\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for POST requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPUT\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PUT requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPATCH\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PATCH requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenJSONP\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for JSONP requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\nangular.mock.e2e = {};\nangular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];\n\n\nangular.mock.clearDataCache = function() {\n  var key,\n      cache = angular.element.cache;\n\n  for(key in cache) {\n    if (cache.hasOwnProperty(key)) {\n      var handle = cache[key].handle;\n\n      handle && angular.element(handle.elem).unbind();\n      delete cache[key];\n    }\n  }\n};\n\n\nwindow.jstestdriver && (function(window) {\n  /**\n   * Global method to output any number of objects into JSTD console. Useful for debugging.\n   */\n  window.dump = function() {\n    var args = [];\n    angular.forEach(arguments, function(arg) {\n      args.push(angular.mock.dump(arg));\n    });\n    jstestdriver.console.log.apply(jstestdriver.console, args);\n    if (window.console) {\n      window.console.log.apply(window.console, args);\n    }\n  };\n})(window);\n\n\nwindow.jasmine && (function(window) {\n\n  afterEach(function() {\n    var spec = getCurrentSpec();\n    var injector = spec.$injector;\n\n    spec.$injector = null;\n    spec.$modules = null;\n\n    if (injector) {\n      injector.get('$rootElement').unbind();\n      injector.get('$browser').pollFns.length = 0;\n    }\n\n    angular.mock.clearDataCache();\n\n    // clean up jquery's fragment cache\n    angular.forEach(angular.element.fragments, function(val, key) {\n      delete angular.element.fragments[key];\n    });\n\n    MockXhr.$$lastInstance = null;\n\n    angular.forEach(angular.callbacks, function(val, key) {\n      delete angular.callbacks[key];\n    });\n    angular.callbacks.counter = 0;\n  });\n\n  function getCurrentSpec() {\n    return jasmine.getEnv().currentSpec;\n  }\n\n  function isSpecRunning() {\n    var spec = getCurrentSpec();\n    return spec && spec.queue.running;\n  }\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.module\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * This function registers a module configuration code. It collects the configuration information\n   * which will be used when the injector is created by {@link angular.mock.inject inject}.\n   *\n   * See {@link angular.mock.inject inject} for usage example\n   *\n   * @param {...(string|Function)} fns any number of modules which are represented as string\n   *        aliases or as anonymous module initialization functions. The modules are used to\n   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.\n   */\n  window.module = angular.mock.module = function() {\n    var moduleFns = Array.prototype.slice.call(arguments, 0);\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      if (spec.$injector) {\n        throw Error('Injector already created, can not register a module!');\n      } else {\n        var modules = spec.$modules || (spec.$modules = []);\n        angular.forEach(moduleFns, function(module) {\n          modules.push(module);\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.inject\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * The inject function wraps a function into an injectable function. The inject() creates new\n   * instance of {@link AUTO.$injector $injector} per test, which is then used for\n   * resolving references.\n   *\n   * See also {@link angular.mock.module module}\n   *\n   * Example of what a typical jasmine tests looks like with the inject method.\n   * <pre>\n   *\n   *   angular.module('myApplicationModule', [])\n   *       .value('mode', 'app')\n   *       .value('version', 'v1.0.1');\n   *\n   *\n   *   describe('MyApp', function() {\n   *\n   *     // You need to load modules that you want to test,\n   *     // it loads only the \"ng\" module by default.\n   *     beforeEach(module('myApplicationModule'));\n   *\n   *\n   *     // inject() is used to inject arguments of all given functions\n   *     it('should provide a version', inject(function(mode, version) {\n   *       expect(version).toEqual('v1.0.1');\n   *       expect(mode).toEqual('app');\n   *     }));\n   *\n   *\n   *     // The inject and module method can also be used inside of the it or beforeEach\n   *     it('should override a version and test the new version is injected', function() {\n   *       // module() takes functions or strings (module aliases)\n   *       module(function($provide) {\n   *         $provide.value('version', 'overridden'); // override version here\n   *       });\n   *\n   *       inject(function(version) {\n   *         expect(version).toEqual('overridden');\n   *       });\n   *     ));\n   *   });\n   *\n   * </pre>\n   *\n   * @param {...Function} fns any number of functions which will be injected using the injector.\n   */\n  window.inject = angular.mock.inject = function() {\n    var blockFns = Array.prototype.slice.call(arguments, 0);\n    var errorForStack = new Error('Declaration Location');\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      var modules = spec.$modules || [];\n      modules.unshift('ngMock');\n      modules.unshift('ng');\n      var injector = spec.$injector;\n      if (!injector) {\n        injector = spec.$injector = angular.injector(modules);\n      }\n      for(var i = 0, ii = blockFns.length; i < ii; i++) {\n        try {\n          injector.invoke(blockFns[i] || angular.noop, this);\n        } catch (e) {\n          if(e.stack) e.stack +=  '\\n' + errorForStack.stack;\n          throw e;\n        } finally {\n          errorForStack = null;\n        }\n      }\n    }\n  };\n})(window);\n"
  },
  {
    "path": "chapter5/recipe4/test/lib/angular/angular-scenario.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Mar 21 12:46:34 2012 -0700\n */\n(function( window, undefined ) {\n'use strict';\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.7.2\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in array && array[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n\t\tvar exec,\n\t\t\tbulk = key == null,\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\n\t\t// Sets many values\n\t\tif ( key && typeof key === \"object\" ) {\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n\t\t\t}\n\t\t\tchainable = 1;\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = pass === undefined && jQuery.isFunction( value );\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations only iterate when executing function values\n\t\t\t\tif ( exec ) {\n\t\t\t\t\texec = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn exec.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\n\t\t\t\t// Otherwise they run against the entire set\n\t\t\t\t} else {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor (; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchainable = 1;\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfired = true;\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar length = list.length;\n\t\t\t\t\tadd( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory || memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tfragment,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tpixelMargin: true\n\t};\n\n\t// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead\n\tjQuery.boxModel = support.boxModel = (document.compatMode === \"CSS1Compat\");\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor ( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\tfragment.removeChild( div );\n\n\t// Null elements to avoid leaks in IE\n\tfragment = select = opt = div = input = null;\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tmarginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,\n\t\t\tpaddingMarginBorderVisibility, paddingMarginBorder,\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tconMarginTop = 1;\n\t\tpaddingMarginBorder = \"padding:0;margin:0;border:\";\n\t\tpositionTopLeftWidthHeight = \"position:absolute;top:0;left:0;width:1px;height:1px;\";\n\t\tpaddingMarginBorderVisibility = paddingMarginBorder + \"0;visibility:hidden;\";\n\t\tstyle = \"style='\" + positionTopLeftWidthHeight + paddingMarginBorder + \"5px solid #000;\";\n\t\thtml = \"<div \" + style + \"display:block;'><div style='\" + paddingMarginBorder + \"0;display:block;overflow:hidden;'></div></div>\" +\n\t\t\t\"<table \" + style + \"' cellpadding='0' cellspacing='0'>\" +\n\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = paddingMarginBorderVisibility + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td style='\" + paddingMarginBorder + \"0;display:none'></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName( \"td\" );\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t// gets computed margin-right based on width of container. For more\n\t\t// info see bug #3333\n\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tmarginDiv = document.createElement( \"div\" );\n\t\t\tmarginDiv.style.width = \"0\";\n\t\t\tmarginDiv.style.marginRight = \"0\";\n\t\t\tdiv.style.width = \"2px\";\n\t\t\tdiv.appendChild( marginDiv );\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\t// (IE < 8 does this)\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.width = div.style.padding = \"1px\";\n\t\t\tdiv.style.border = 0;\n\t\t\tdiv.style.overflow = \"hidden\";\n\t\t\tdiv.style.display = \"inline\";\n\t\t\tdiv.style.zoom = 1;\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.style.overflow = \"visible\";\n\t\t\tdiv.innerHTML = \"<div style='width:5px;'></div>\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\t\t}\n\n\t\tdiv.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;\n\t\tdiv.innerHTML = html;\n\n\t\touter = div.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.style.marginTop = \"1%\";\n\t\t\tsupport.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== \"1%\";\n\t\t}\n\n\t\tif ( typeof container.style.zoom !== \"undefined\" ) {\n\t\t\tcontainer.style.zoom = 1;\n\t\t}\n\n\t\tbody.removeChild( container );\n\t\tmarginDiv = div = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\treturn support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ internalKey ] : internalKey;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ internalKey ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( internalKey );\n\t\t\t} else {\n\t\t\t\telem[ internalKey ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, part, attr, name, l,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = elem.attributes;\n\t\t\t\t\tfor ( l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split( \".\", 2 );\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\t\tpart = parts[1] + \"!\";\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\tdata = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\tif ( data === undefined && elem ) {\n\t\t\t\t\tdata = jQuery.data( elem, key );\n\t\t\t\t\tdata = dataAttr( elem, key, data );\n\t\t\t\t}\n\n\t\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\t\tdata;\n\t\t\t}\n\n\t\t\tparts[1] = value;\n\t\t\tthis.each(function() {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.triggerHandler( \"setData\" + part, parts );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + part, parts );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, false );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\thooks = {};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( object );\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, l, isBool,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\t\t\tattrNames = value.toLowerCase().split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tisBool = rboolean.test( name );\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\t// Do not do this for boolean attributes (see #10870)\n\t\t\t\t\tif ( !isBool ) {\n\t\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\t}\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( isBool && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true,\n\t\tcoords: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = \"\" + value );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+)?\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\tvar attrs = elem.attributes || {};\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || (attrs.id || {}).value === m[2]) &&\n\t\t\t(!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tquick: selector && quickParse( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t ( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\told = null;\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\tspecial = jQuery.event.special[ event.type ] || {},\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n\t\t\t// Pregenerate a single jQuery object for reuse with .is()\n\t\t\tjqcur = jQuery(this);\n\t\t\tjqcur.context = this.ownerDocument || this;\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process events on disabled elements (#6911, #8165)\n\t\t\t\tif ( cur.disabled !== true ) {\n\t\t\t\t\tselMatch = {};\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tjqcur[0] = cur;\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\t\tselMatch[ sel ] = (\n\t\t\t\t\t\t\t\thandleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\tret;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\t\t\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\telem._change_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) { // && selector != null\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( var type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\n\t\t\tparts.push( m[1] );\n\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\t\t/* falls through */\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n// Expose origPOS\n// \"global\" as in regardless of relation to brackets/parens\nExpr.match.globalPOS = origPOS;\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry {\n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.globalPOS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\tPOS.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery.clean(arguments) );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tnull;\n\t\t\t}\n\n\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, function( i, elem ) {\n\t\t\t\t\tif ( elem.src ) {\n\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\turl: elem.src,\n\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\tdataType: \"script\"\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\n\t// IE blanks contents when cloning scripts\n\t} else if ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdest.text = src.text;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n\n\t// Clear flags for bubbling special change/submit events, they must\n\t// be reattached when the newly cloned events are first activated\n\tdest.removeAttribute( \"_submit_attached\" );\n\tdest.removeAttribute( \"_change_attached\" );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n\t// Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n\tvar div = document.createElement( \"div\" );\n\tsafeFragment.appendChild( div );\n\n\tdiv.innerHTML = elem.outerHTML;\n\treturn div.firstChild;\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t\tclone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ?\n\t\t\t\telem.cloneNode( true ) :\n\t\t\t\tshimCloneNode( elem );\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType, script, j,\n\t\t\t\tret = [];\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\"),\n\t\t\t\t\t\tsafeChildNodes = safeFragment.childNodes,\n\t\t\t\t\t\tremove;\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\n\t\t\t\t\t// Clear elements from DocumentFragment (safeFragment or otherwise)\n\t\t\t\t\t// to avoid hoarding elements. Fixes #11356\n\t\t\t\t\tif ( div ) {\n\t\t\t\t\t\tdiv.parentNode.removeChild( div );\n\n\t\t\t\t\t\t// Guard against -1 index exceptions in FF3.6\n\t\t\t\t\t\tif ( safeChildNodes.length > 0 ) {\n\t\t\t\t\t\t\tremove = safeChildNodes[ safeChildNodes.length - 1 ];\n\n\t\t\t\t\t\t\tif ( remove && remove.parentNode ) {\n\t\t\t\t\t\t\t\tremove.parentNode.removeChild( remove );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tscript = ret[i];\n\t\t\t\tif ( scripts && jQuery.nodeName( script, \"script\" ) && (!script.type || rscriptType.test( script.type )) ) {\n\t\t\t\t\tscripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( script.nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( script.getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( script );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnum = /^[\\-+]?(?:\\d*\\.)?\\d+$/i,\n\trnumnonpx = /^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\trmargin = /^margin/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\n\t// order is important!\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\treturn jQuery.access( this, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t}, name, value, arguments.length > 1 );\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {},\n\t\t\tret, name;\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// DEPRECATED in 1.3, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle, width,\n\t\t\tstyle = elem.style;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( (defaultView = elem.ownerDocument.defaultView) &&\n\t\t\t\t(computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// WebKit uses \"computed value (percentage if specified)\" instead of \"used value\" for margins\n\t\t// which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {\n\t\t\twidth = style.width;\n\t\t\tstyle.width = ret;\n\t\t\tret = computedStyle.width;\n\t\t\tstyle.width = width;\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( rnumnonpx.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\ti = name === \"width\" ? 1 : 0,\n\t\tlen = 4;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tfor ( ; i < len; i += 2 ) {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ];\n\t}\n\n\t// Computed unit is not pixels. Stop here and return.\n\tif ( rnumnonpx.test(val) ) {\n\t\treturn val;\n\t}\n\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tfor ( ; i < len; i += 2 ) {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val + \"px\";\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\treturn jQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\treturn rnum.test( value ) ?\n\t\t\t\tvalue + \"px\" :\n\t\t\t\tvalue;\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\treturn curCSS( elem, \"margin-right\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i,\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n\t\t\t\texpanded = {};\n\n\t\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n});\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = ( typeof s.data === \"string\" ) && /^application\\/x\\-www\\-form\\-urlencoded/.test( s.contentType );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t} catch( _ ) {\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( (display === \"\" && jQuery.css(elem, \"display\") === \"none\") ||\n\t\t\t\t\t\t!jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e, hooks, replace,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\t// first pass over propertys to expand / normalize\n\t\t\tfor ( p in prop ) {\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tif ( ( hooks = jQuery.cssHooks[ name ] ) && \"expand\" in hooks ) {\n\t\t\t\t\treplace = hooks.expand( prop[ name ] );\n\t\t\t\t\tdelete prop[ name ];\n\n\t\t\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t\t\t// also - reusing 'p' from above because we have the correct \"name\"\n\t\t\t\t\tfor ( p in replace ) {\n\t\t\t\t\t\tif ( ! ( p in prop ) ) {\n\t\t\t\t\t\t\tprop[ p ] = replace[ p ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( name in prop ) {\n\t\t\t\tval = prop[ name ];\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, index ) {\n\t\t\t\tvar hooks = data[ index ];\n\t\t\t\tjQuery.removeData( elem, index, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n\t\t\t\tstopQueue( this, data, index );\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ index ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ index ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p ) {\n\t\t\treturn p;\n\t\t},\n\t\tswing: function( p ) {\n\t\t\treturn ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tif ( self.options.hide ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t\t} else if ( self.options.show ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.end );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Ensure props that can't be negative don't go there on undershoot easing\njQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {\n\t// exclude marginTop, marginLeft, marginBottom and marginRight from this list\n\tif ( prop.indexOf( \"margin\" ) ) {\n\t\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( jQuery.support.boxModel ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar getOffset,\n\trtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tgetOffset = function( elem, doc, docElem, box ) {\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow( doc ),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tgetOffset = function( elem, doc, docElem ) {\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar elem = this[0],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn null;\n\t}\n\n\tif ( elem === doc.body ) {\n\t\treturn jQuery.offset.bodyOffset( elem );\n\t}\n\n\treturn getOffset( elem, doc, doc.documentElement );\n};\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t top ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tvar clientProp = \"client\" + name,\n\t\tscrollProp = \"scroll\" + name,\n\t\toffsetProp = \"offset\" + name;\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( value ) {\n\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\tvar doc, docElemProp, orig, ret;\n\n\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\t\tdoc = elem.document;\n\t\t\t\tdocElemProp = doc.documentElement[ clientProp ];\n\t\t\t\treturn jQuery.support.boxModel && docElemProp ||\n\t\t\t\t\tdoc.body && doc.body[ clientProp ] || docElemProp;\n\t\t\t}\n\n\t\t\t// Get document width or height\n\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t// when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]\n\t\t\t\t// so we can't use max, as it'll choose the incorrect offset[Width/Height]\n\t\t\t\t// instead we use the correct client[Width/Height]\n\t\t\t\t// support:IE6\n\t\t\t\tif ( doc[ clientProp ] >= doc[ scrollProp ] ) {\n\t\t\t\t\treturn doc[ clientProp ];\n\t\t\t\t}\n\n\t\t\t\treturn Math.max(\n\t\t\t\t\telem.body[ scrollProp ], doc[ scrollProp ],\n\t\t\t\t\telem.body[ offsetProp ], doc[ offsetProp ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get width or height on the element\n\t\t\tif ( value === undefined ) {\n\t\t\t\torig = jQuery.css( elem, type );\n\t\t\t\tret = parseFloat( orig );\n\t\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\t\t\t}\n\n\t\t\t// Set the width or height on the element\n\t\t\tjQuery( elem ).css( type, value );\n\t\t}, type, value, arguments.length, null );\n\t};\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );\n/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document){\n  var _jQuery = window.jQuery.noConflict(true);\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n\n/**\n * Setup file for the Scenario.\n * Must be first in the compilation/bootstrap list.\n */\n\n// Public namespace\nangular.scenario = angular.scenario || {};\n\n/**\n * Defines a new output format.\n *\n * @param {string} name the name of the new output format\n * @param {function()} fn function(context, runner) that generates the output\n */\nangular.scenario.output = angular.scenario.output || function(name, fn) {\n  angular.scenario.output[name] = fn;\n};\n\n/**\n * Defines a new DSL statement. If your factory function returns a Future\n * it's returned, otherwise the result is assumed to be a map of functions\n * for chaining. Chained functions are subject to the same rules.\n *\n * Note: All functions on the chain are bound to the chain scope so values\n *   set on \"this\" in your statement function are available in the chained\n *   functions.\n *\n * @param {string} name The name of the statement\n * @param {function()} fn Factory function(), return a function for\n *  the statement.\n */\nangular.scenario.dsl = angular.scenario.dsl || function(name, fn) {\n  angular.scenario.dsl[name] = function() {\n    function executeStatement(statement, args) {\n      var result = statement.apply(this, args);\n      if (angular.isFunction(result) || result instanceof angular.scenario.Future)\n        return result;\n      var self = this;\n      var chain = angular.extend({}, result);\n      angular.forEach(chain, function(value, name) {\n        if (angular.isFunction(value)) {\n          chain[name] = function() {\n            return executeStatement.call(self, value, arguments);\n          };\n        } else {\n          chain[name] = value;\n        }\n      });\n      return chain;\n    }\n    var statement = fn.apply(this, arguments);\n    return function() {\n      return executeStatement.call(this, statement, arguments);\n    };\n  };\n};\n\n/**\n * Defines a new matcher for use with the expects() statement. The value\n * this.actual (like in Jasmine) is available in your matcher to compare\n * against. Your function should return a boolean. The future is automatically\n * created for you.\n *\n * @param {string} name The name of the matcher\n * @param {function()} fn The matching function(expected).\n */\nangular.scenario.matcher = angular.scenario.matcher || function(name, fn) {\n  angular.scenario.matcher[name] = function(expected) {\n    var prefix = 'expect ' + this.future.name + ' ';\n    if (this.inverse) {\n      prefix += 'not ';\n    }\n    var self = this;\n    this.addFuture(prefix + name + ' ' + angular.toJson(expected),\n      function(done) {\n        var error;\n        self.actual = self.future.value;\n        if ((self.inverse && fn.call(self, expected)) ||\n            (!self.inverse && !fn.call(self, expected))) {\n          error = 'expected ' + angular.toJson(expected) +\n            ' but was ' + angular.toJson(self.actual);\n        }\n        done(error);\n    });\n  };\n};\n\n/**\n * Initialize the scenario runner and run !\n *\n * Access global window and document object\n * Access $runner through closure\n *\n * @param {Object=} config Config options\n */\nangular.scenario.setUpAndRun = function(config) {\n  var href = window.location.href;\n  var body = _jQuery(document.body);\n  var output = [];\n  var objModel = new angular.scenario.ObjectModel($runner);\n\n  if (config && config.scenario_output) {\n    output = config.scenario_output.split(',');\n  }\n\n  angular.forEach(angular.scenario.output, function(fn, name) {\n    if (!output.length || indexOf(output,name) != -1) {\n      var context = body.append('<div></div>').find('div:last');\n      context.attr('id', name);\n      fn.call({}, context, $runner, objModel);\n    }\n  });\n\n  if (!/^http/.test(href) && !/^https/.test(href)) {\n    body.append('<p id=\"system-error\"></p>');\n    body.find('#system-error').text(\n      'Scenario runner must be run using http or https. The protocol ' +\n      href.split(':')[0] + ':// is not supported.'\n    );\n    return;\n  }\n\n  var appFrame = body.append('<div id=\"application\"></div>').find('#application');\n  var application = new angular.scenario.Application(appFrame);\n\n  $runner.on('RunnerEnd', function() {\n    appFrame.css('display', 'none');\n    appFrame.find('iframe').attr('src', 'about:blank');\n  });\n\n  $runner.on('RunnerError', function(error) {\n    if (window.console) {\n      console.log(formatException(error));\n    } else {\n      // Do something for IE\n      alert(error);\n    }\n  });\n\n  $runner.run(application);\n};\n\n/**\n * Iterates through list with iterator function that must call the\n * continueFunction to continute iterating.\n *\n * @param {Array} list list to iterate over\n * @param {function()} iterator Callback function(value, continueFunction)\n * @param {function()} done Callback function(error, result) called when\n *   iteration finishes or an error occurs.\n */\nfunction asyncForEach(list, iterator, done) {\n  var i = 0;\n  function loop(error, index) {\n    if (index && index > i) {\n      i = index;\n    }\n    if (error || i >= list.length) {\n      done(error);\n    } else {\n      try {\n        iterator(list[i++], loop);\n      } catch (e) {\n        done(e);\n      }\n    }\n  }\n  loop();\n}\n\n/**\n * Formats an exception into a string with the stack trace, but limits\n * to a specific line length.\n *\n * @param {Object} error The exception to format, can be anything throwable\n * @param {Number=} [maxStackLines=5] max lines of the stack trace to include\n *  default is 5.\n */\nfunction formatException(error, maxStackLines) {\n  maxStackLines = maxStackLines || 5;\n  var message = error.toString();\n  if (error.stack) {\n    var stack = error.stack.split('\\n');\n    if (stack[0].indexOf(message) === -1) {\n      maxStackLines++;\n      stack.unshift(error.message);\n    }\n    message = stack.slice(0, maxStackLines).join('\\n');\n  }\n  return message;\n}\n\n/**\n * Returns a function that gets the file name and line number from a\n * location in the stack if available based on the call site.\n *\n * Note: this returns another function because accessing .stack is very\n * expensive in Chrome.\n *\n * @param {Number} offset Number of stack lines to skip\n */\nfunction callerFile(offset) {\n  var error = new Error();\n\n  return function() {\n    var line = (error.stack || '').split('\\n')[offset];\n\n    // Clean up the stack trace line\n    if (line) {\n      if (line.indexOf('@') !== -1) {\n        // Firefox\n        line = line.substring(line.indexOf('@')+1);\n      } else {\n        // Chrome\n        line = line.substring(line.indexOf('(')+1).replace(')', '');\n      }\n    }\n\n    return line || '';\n  };\n}\n\n/**\n * Triggers a browser event. Attempts to choose the right event if one is\n * not specified.\n *\n * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement\n * @param {string} type Optional event type.\n * @param {Array.<string>=} keys Optional list of pressed keys\n *        (valid values: 'alt', 'meta', 'shift', 'ctrl')\n */\nfunction browserTrigger(element, type, keys) {\n  if (element && !element.nodeName) element = element[0];\n  if (!element) return;\n  if (!type) {\n    type = {\n        'text':            'change',\n        'textarea':        'change',\n        'hidden':          'change',\n        'password':        'change',\n        'button':          'click',\n        'submit':          'click',\n        'reset':           'click',\n        'image':           'click',\n        'checkbox':        'click',\n        'radio':           'click',\n        'select-one':      'change',\n        'select-multiple': 'change'\n    }[lowercase(element.type)] || 'click';\n  }\n  if (lowercase(nodeName_(element)) == 'option') {\n    element.parentNode.value = element.value;\n    element = element.parentNode;\n    type = 'change';\n  }\n\n  keys = keys || [];\n  function pressed(key) {\n    return indexOf(keys, key) !== -1;\n  }\n\n  if (msie < 9) {\n    switch(element.type) {\n      case 'radio':\n      case 'checkbox':\n        element.checked = !element.checked;\n        break;\n    }\n    // WTF!!! Error: Unspecified error.\n    // Don't know why, but some elements when detached seem to be in inconsistent state and\n    // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)\n    // forcing the browser to compute the element position (by reading its CSS)\n    // puts the element in consistent state.\n    element.style.posLeft;\n\n    // TODO(vojta): create event objects with pressed keys to get it working on IE<9\n    var ret = element.fireEvent('on' + type);\n    if (lowercase(element.type) == 'submit') {\n      while(element) {\n        if (lowercase(element.nodeName) == 'form') {\n          element.fireEvent('onsubmit');\n          break;\n        }\n        element = element.parentNode;\n      }\n    }\n    return ret;\n  } else {\n    var evnt = document.createEvent('MouseEvents'),\n        originalPreventDefault = evnt.preventDefault,\n        iframe = _jQuery('#application iframe')[0],\n        appWindow = iframe ? iframe.contentWindow : window,\n        fakeProcessDefault = true,\n        finalProcessDefault,\n        angular = appWindow.angular || {};\n\n    // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208\n    angular['ff-684208-preventDefault'] = false;\n    evnt.preventDefault = function() {\n      fakeProcessDefault = false;\n      return originalPreventDefault.apply(evnt, arguments);\n    };\n\n    evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, pressed('ctrl'), pressed('alt'),\n                        pressed('shift'), pressed('meta'), 0, element);\n\n    element.dispatchEvent(evnt);\n    finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);\n\n    delete angular['ff-684208-preventDefault'];\n\n    return finalProcessDefault;\n  }\n}\n\n/**\n * Don't use the jQuery trigger method since it works incorrectly.\n *\n * jQuery notifies listeners and then changes the state of a checkbox and\n * does not create a real browser event. A real click changes the state of\n * the checkbox and then notifies listeners.\n *\n * To work around this we instead use our own handler that fires a real event.\n */\n(function(fn){\n  var parentTrigger = fn.trigger;\n  fn.trigger = function(type) {\n    if (/(click|change|keydown|blur|input)/.test(type)) {\n      var processDefaults = [];\n      this.each(function(index, node) {\n        processDefaults.push(browserTrigger(node, type));\n      });\n\n      // this is not compatible with jQuery - we return an array of returned values,\n      // so that scenario runner know whether JS code has preventDefault() of the event or not...\n      return processDefaults;\n    }\n    return parentTrigger.apply(this, arguments);\n  };\n})(_jQuery.fn);\n\n/**\n * Finds all bindings with the substring match of name and returns an\n * array of their values.\n *\n * @param {string} bindExp The name to match\n * @return {Array.<string>} String of binding values\n */\n_jQuery.fn.bindings = function(windowJquery, bindExp) {\n  var result = [], match,\n      bindSelector = '.ng-binding:visible';\n  if (angular.isString(bindExp)) {\n    bindExp = bindExp.replace(/\\s/g, '');\n    match = function (actualExp) {\n      if (actualExp) {\n        actualExp = actualExp.replace(/\\s/g, '');\n        if (actualExp == bindExp) return true;\n        if (actualExp.indexOf(bindExp) == 0) {\n          return actualExp.charAt(bindExp.length) == '|';\n        }\n      }\n    }\n  } else if (bindExp) {\n    match = function(actualExp) {\n      return actualExp && bindExp.exec(actualExp);\n    }\n  } else {\n    match = function(actualExp) {\n      return !!actualExp;\n    };\n  }\n  var selection = this.find(bindSelector);\n  if (this.is(bindSelector)) {\n    selection = selection.add(this);\n  }\n\n  function push(value) {\n    if (value == undefined) {\n      value = '';\n    } else if (typeof value != 'string') {\n      value = angular.toJson(value);\n    }\n    result.push('' + value);\n  }\n\n  selection.each(function() {\n    var element = windowJquery(this),\n        binding;\n    if (binding = element.data('$binding')) {\n      if (typeof binding == 'string') {\n        if (match(binding)) {\n          push(element.scope().$eval(binding));\n        }\n      } else {\n        if (!angular.isArray(binding)) {\n          binding = [binding];\n        }\n        for(var fns, j=0, jj=binding.length;  j<jj; j++) {\n          fns = binding[j];\n          if (fns.parts) {\n            fns = fns.parts;\n          } else {\n            fns = [fns];\n          }\n          for (var scope, fn, i = 0, ii = fns.length; i < ii; i++) {\n            if(match((fn = fns[i]).exp)) {\n              push(fn(scope = scope || element.scope()));\n            }\n          }\n        }\n      }\n    }\n  });\n  return result;\n};\n\n/**\n * Represents the application currently being tested and abstracts usage\n * of iframes or separate windows.\n *\n * @param {Object} context jQuery wrapper around HTML context.\n */\nangular.scenario.Application = function(context) {\n  this.context = context;\n  context.append(\n    '<h2>Current URL: <a href=\"about:blank\">None</a></h2>' +\n    '<div id=\"test-frames\"></div>'\n  );\n};\n\n/**\n * Gets the jQuery collection of frames. Don't use this directly because\n * frames may go stale.\n *\n * @private\n * @return {Object} jQuery collection\n */\nangular.scenario.Application.prototype.getFrame_ = function() {\n  return this.context.find('#test-frames iframe:last');\n};\n\n/**\n * Gets the window of the test runner frame. Always favor executeAction()\n * instead of this method since it prevents you from getting a stale window.\n *\n * @private\n * @return {Object} the window of the frame\n */\nangular.scenario.Application.prototype.getWindow_ = function() {\n  var contentWindow = this.getFrame_().prop('contentWindow');\n  if (!contentWindow)\n    throw 'Frame window is not accessible.';\n  return contentWindow;\n};\n\n/**\n * Changes the location of the frame.\n *\n * @param {string} url The URL. If it begins with a # then only the\n *   hash of the page is changed.\n * @param {function()} loadFn function($window, $document) Called when frame loads.\n * @param {function()} errorFn function(error) Called if any error when loading.\n */\nangular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorFn) {\n  var self = this;\n  var frame = this.getFrame_();\n  //TODO(esprehn): Refactor to use rethrow()\n  errorFn = errorFn || function(e) { throw e; };\n  if (url === 'about:blank') {\n    errorFn('Sandbox Error: Navigating to about:blank is not allowed.');\n  } else if (url.charAt(0) === '#') {\n    url = frame.attr('src').split('#')[0] + url;\n    frame.attr('src', url);\n    this.executeAction(loadFn);\n  } else {\n    frame.remove();\n    this.context.find('#test-frames').append('<iframe>');\n    frame = this.getFrame_();\n    frame.load(function() {\n      frame.unbind();\n      try {\n        self.executeAction(loadFn);\n      } catch (e) {\n        errorFn(e);\n      }\n    }).attr('src', url);\n  }\n  this.context.find('> h2 a').attr('href', url).text(url);\n};\n\n/**\n * Executes a function in the context of the tested application. Will wait\n * for all pending angular xhr requests before executing.\n *\n * @param {function()} action The callback to execute. function($window, $document)\n *  $document is a jQuery wrapped document.\n */\nangular.scenario.Application.prototype.executeAction = function(action) {\n  var self = this;\n  var $window = this.getWindow_();\n  if (!$window.document) {\n    throw 'Sandbox Error: Application document not accessible.';\n  }\n  if (!$window.angular) {\n    return action.call(this, $window, _jQuery($window.document));\n  }\n  angularInit($window.document, function(element) {\n    var $injector = $window.angular.element(element).injector();\n    var $element = _jQuery(element);\n\n    $element.injector = function() {\n      return $injector;\n    };\n\n    $injector.invoke(function($browser){\n      $browser.notifyWhenNoOutstandingRequests(function() {\n        action.call(self, $window, $element);\n      });\n    });\n  });\n};\n\n/**\n * The representation of define blocks. Don't used directly, instead use\n * define() in your tests.\n *\n * @param {string} descName Name of the block\n * @param {Object} parent describe or undefined if the root.\n */\nangular.scenario.Describe = function(descName, parent) {\n  this.only = parent && parent.only;\n  this.beforeEachFns = [];\n  this.afterEachFns = [];\n  this.its = [];\n  this.children = [];\n  this.name = descName;\n  this.parent = parent;\n  this.id = angular.scenario.Describe.id++;\n\n  /**\n   * Calls all before functions.\n   */\n  var beforeEachFns = this.beforeEachFns;\n  this.setupBefore = function() {\n    if (parent) parent.setupBefore.call(this);\n    angular.forEach(beforeEachFns, function(fn) { fn.call(this); }, this);\n  };\n\n  /**\n   * Calls all after functions.\n   */\n  var afterEachFns = this.afterEachFns;\n  this.setupAfter  = function() {\n    angular.forEach(afterEachFns, function(fn) { fn.call(this); }, this);\n    if (parent) parent.setupAfter.call(this);\n  };\n};\n\n// Shared Unique ID generator for every describe block\nangular.scenario.Describe.id = 0;\n\n// Shared Unique ID generator for every it (spec)\nangular.scenario.Describe.specId = 0;\n\n/**\n * Defines a block to execute before each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.beforeEach = function(body) {\n  this.beforeEachFns.push(body);\n};\n\n/**\n * Defines a block to execute after each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.afterEach = function(body) {\n  this.afterEachFns.push(body);\n};\n\n/**\n * Creates a new describe block that's a child of this one.\n *\n * @param {string} name Name of the block. Appended to the parent block's name.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.describe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Same as describe() but makes ddescribe blocks the only to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.ddescribe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  child.only = true;\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Use to disable a describe block.\n */\nangular.scenario.Describe.prototype.xdescribe = angular.noop;\n\n/**\n * Defines a test.\n *\n * @param {string} name Name of the test.\n * @param {function()} vody Body of the block.\n */\nangular.scenario.Describe.prototype.it = function(name, body) {\n  this.its.push({\n    id: angular.scenario.Describe.specId++,\n    definition: this,\n    only: this.only,\n    name: name,\n    before: this.setupBefore,\n    body: body,\n    after: this.setupAfter\n  });\n};\n\n/**\n * Same as it() but makes iit tests the only test to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.iit = function(name, body) {\n  this.it.apply(this, arguments);\n  this.its[this.its.length-1].only = true;\n};\n\n/**\n * Use to disable a test block.\n */\nangular.scenario.Describe.prototype.xit = angular.noop;\n\n/**\n * Gets an array of functions representing all the tests (recursively).\n * that can be executed with SpecRunner's.\n *\n * @return {Array<Object>} Array of it blocks {\n *   definition : Object // parent Describe\n *   only: boolean\n *   name: string\n *   before: Function\n *   body: Function\n *   after: Function\n *  }\n */\nangular.scenario.Describe.prototype.getSpecs = function() {\n  var specs = arguments[0] || [];\n  angular.forEach(this.children, function(child) {\n    child.getSpecs(specs);\n  });\n  angular.forEach(this.its, function(it) {\n    specs.push(it);\n  });\n  var only = [];\n  angular.forEach(specs, function(it) {\n    if (it.only) {\n      only.push(it);\n    }\n  });\n  return (only.length && only) || specs;\n};\n\n/**\n * A future action in a spec.\n *\n * @param {string} name of the future action\n * @param {function()} future callback(error, result)\n * @param {function()} Optional. function that returns the file/line number.\n */\nangular.scenario.Future = function(name, behavior, line) {\n  this.name = name;\n  this.behavior = behavior;\n  this.fulfilled = false;\n  this.value = undefined;\n  this.parser = angular.identity;\n  this.line = line || function() { return ''; };\n};\n\n/**\n * Executes the behavior of the closure.\n *\n * @param {function()} doneFn Callback function(error, result)\n */\nangular.scenario.Future.prototype.execute = function(doneFn) {\n  var self = this;\n  this.behavior(function(error, result) {\n    self.fulfilled = true;\n    if (result) {\n      try {\n        result = self.parser(result);\n      } catch(e) {\n        error = e;\n      }\n    }\n    self.value = error || result;\n    doneFn(error, result);\n  });\n};\n\n/**\n * Configures the future to convert it's final with a function fn(value)\n *\n * @param {function()} fn function(value) that returns the parsed value\n */\nangular.scenario.Future.prototype.parsedWith = function(fn) {\n  this.parser = fn;\n  return this;\n};\n\n/**\n * Configures the future to parse it's final value from JSON\n * into objects.\n */\nangular.scenario.Future.prototype.fromJson = function() {\n  return this.parsedWith(angular.fromJson);\n};\n\n/**\n * Configures the future to convert it's final value from objects\n * into JSON.\n */\nangular.scenario.Future.prototype.toJson = function() {\n  return this.parsedWith(angular.toJson);\n};\n\n/**\n * Maintains an object tree from the runner events.\n *\n * @param {Object} runner The scenario Runner instance to connect to.\n *\n * TODO(esprehn): Every output type creates one of these, but we probably\n *  want one global shared instance. Need to handle events better too\n *  so the HTML output doesn't need to do spec model.getSpec(spec.id)\n *  silliness.\n *\n * TODO(vojta) refactor on, emit methods (from all objects) - use inheritance\n */\nangular.scenario.ObjectModel = function(runner) {\n  var self = this;\n\n  this.specMap = {};\n  this.listeners = [];\n  this.value = {\n    name: '',\n    children: {}\n  };\n\n  runner.on('SpecBegin', function(spec) {\n    var block = self.value,\n        definitions = [];\n\n    angular.forEach(self.getDefinitionPath(spec), function(def) {\n      if (!block.children[def.name]) {\n        block.children[def.name] = {\n          id: def.id,\n          name: def.name,\n          children: {},\n          specs: {}\n        };\n      }\n      block = block.children[def.name];\n      definitions.push(def.name);\n    });\n\n    var it = self.specMap[spec.id] =\n             block.specs[spec.name] =\n             new angular.scenario.ObjectModel.Spec(spec.id, spec.name, definitions);\n\n    // forward the event\n    self.emit('SpecBegin', it);\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var it = self.getSpec(spec.id);\n    it.status = 'error';\n    it.error = error;\n\n    // forward the event\n    self.emit('SpecError', it, error);\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    complete(it);\n\n    // forward the event\n    self.emit('SpecEnd', it);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var it = self.getSpec(spec.id);\n    var step = new angular.scenario.ObjectModel.Step(step.name);\n    it.steps.push(step);\n\n    // forward the event\n    self.emit('StepBegin', it, step);\n  });\n\n  runner.on('StepEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    var step = it.getLastStep();\n    if (step.name !== step.name)\n      throw 'Events fired in the wrong order. Step names don\\'t match.';\n    complete(step);\n\n    // forward the event\n    self.emit('StepEnd', it, step);\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('failure', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepFailure', it, modelStep, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('error', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepError', it, modelStep, error);\n  });\n\n  runner.on('RunnerBegin', function() {\n    self.emit('RunnerBegin');\n  });\n  runner.on('RunnerEnd', function() {\n    self.emit('RunnerEnd');\n  });\n\n  function complete(item) {\n    item.endTime = new Date().getTime();\n    item.duration = item.endTime - item.startTime;\n    item.status = item.status || 'success';\n  }\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName Name of the event to add a handler for\n * @param {function()} listener Function that will be called when event is fired\n */\nangular.scenario.ObjectModel.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.ObjectModel.prototype.emit = function(eventName) {\n  var self = this,\n      args = Array.prototype.slice.call(arguments, 1),\n      eventName = eventName.toLowerCase();\n\n  if (this.listeners[eventName]) {\n    angular.forEach(this.listeners[eventName], function(listener) {\n      listener.apply(self, args);\n    });\n  }\n};\n\n/**\n * Computes the path of definition describe blocks that wrap around\n * this spec.\n *\n * @param spec Spec to compute the path for.\n * @return {Array<Describe>} The describe block path\n */\nangular.scenario.ObjectModel.prototype.getDefinitionPath = function(spec) {\n  var path = [];\n  var currentDefinition = spec.definition;\n  while (currentDefinition && currentDefinition.name) {\n    path.unshift(currentDefinition);\n    currentDefinition = currentDefinition.parent;\n  }\n  return path;\n};\n\n/**\n * Gets a spec by id.\n *\n * @param {string} The id of the spec to get the object for.\n * @return {Object} the Spec instance\n */\nangular.scenario.ObjectModel.prototype.getSpec = function(id) {\n  return this.specMap[id];\n};\n\n/**\n * A single it block.\n *\n * @param {string} id Id of the spec\n * @param {string} name Name of the spec\n * @param {Array<string>=} definitionNames List of all describe block names that wrap this spec\n */\nangular.scenario.ObjectModel.Spec = function(id, name, definitionNames) {\n  this.id = id;\n  this.name = name;\n  this.startTime = new Date().getTime();\n  this.steps = [];\n  this.fullDefinitionName = (definitionNames || []).join(' ');\n};\n\n/**\n * Adds a new step to the Spec.\n *\n * @param {string} step Name of the step (really name of the future)\n * @return {Object} the added step\n */\nangular.scenario.ObjectModel.Spec.prototype.addStep = function(name) {\n  var step = new angular.scenario.ObjectModel.Step(name);\n  this.steps.push(step);\n  return step;\n};\n\n/**\n * Gets the most recent step.\n *\n * @return {Object} the step\n */\nangular.scenario.ObjectModel.Spec.prototype.getLastStep = function() {\n  return this.steps[this.steps.length-1];\n};\n\n/**\n * Set status of the Spec from given Step\n *\n * @param {angular.scenario.ObjectModel.Step} step\n */\nangular.scenario.ObjectModel.Spec.prototype.setStatusFromStep = function(step) {\n  if (!this.status || step.status == 'error') {\n    this.status = step.status;\n    this.error = step.error;\n    this.line = step.line;\n  }\n};\n\n/**\n * A single step inside a Spec.\n *\n * @param {string} step Name of the step\n */\nangular.scenario.ObjectModel.Step = function(name) {\n  this.name = name;\n  this.startTime = new Date().getTime();\n};\n\n/**\n * Helper method for setting all error status related properties\n *\n * @param {string} status\n * @param {string} error\n * @param {string} line\n */\nangular.scenario.ObjectModel.Step.prototype.setErrorStatus = function(status, error, line) {\n  this.status = status;\n  this.error = error;\n  this.line = line;\n};\n\n/**\n * Runner for scenarios\n *\n * Has to be initialized before any test is loaded,\n * because it publishes the API into window (global space).\n */\nangular.scenario.Runner = function($window) {\n  this.listeners = [];\n  this.$window = $window;\n  this.rootDescribe = new angular.scenario.Describe();\n  this.currentDescribe = this.rootDescribe;\n  this.api = {\n    it: this.it,\n    iit: this.iit,\n    xit: angular.noop,\n    describe: this.describe,\n    ddescribe: this.ddescribe,\n    xdescribe: angular.noop,\n    beforeEach: this.beforeEach,\n    afterEach: this.afterEach\n  };\n  angular.forEach(this.api, angular.bind(this, function(fn, key) {\n    this.$window[key] = angular.bind(this, fn);\n  }));\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.Runner.prototype.emit = function(eventName) {\n  var self = this;\n  var args = Array.prototype.slice.call(arguments, 1);\n  eventName = eventName.toLowerCase();\n  if (!this.listeners[eventName])\n    return;\n  angular.forEach(this.listeners[eventName], function(listener) {\n    listener.apply(self, args);\n  });\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName The name of the event to add a handler for\n * @param {string} listener The fn(...) that takes the extra arguments from emit()\n */\nangular.scenario.Runner.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Defines a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.describe = function(name, body) {\n  var self = this;\n  this.currentDescribe.describe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Same as describe, but makes ddescribe the only blocks to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.ddescribe = function(name, body) {\n  var self = this;\n  this.currentDescribe.ddescribe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Defines a test in a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.it = function(name, body) {\n  this.currentDescribe.it(name, body);\n};\n\n/**\n * Same as it, but makes iit tests the only tests to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.iit = function(name, body) {\n  this.currentDescribe.iit(name, body);\n};\n\n/**\n * Defines a function to be called before each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.beforeEach = function(body) {\n  this.currentDescribe.beforeEach(body);\n};\n\n/**\n * Defines a function to be called after each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.afterEach = function(body) {\n  this.currentDescribe.afterEach(body);\n};\n\n/**\n * Creates a new spec runner.\n *\n * @private\n * @param {Object} scope parent scope\n */\nangular.scenario.Runner.prototype.createSpecRunner_ = function(scope) {\n  var child = scope.$new();\n  var Cls = angular.scenario.SpecRunner;\n\n  // Export all the methods to child scope manually as now we don't mess controllers with scopes\n  // TODO(vojta): refactor scenario runner so that these objects are not tightly coupled as current\n  for (var name in Cls.prototype)\n    child[name] = angular.bind(child, Cls.prototype[name]);\n\n  Cls.call(child);\n  return child;\n};\n\n/**\n * Runs all the loaded tests with the specified runner class on the\n * provided application.\n *\n * @param {angular.scenario.Application} application App to remote control.\n */\nangular.scenario.Runner.prototype.run = function(application) {\n  var self = this;\n  var $root = angular.injector(['ng']).get('$rootScope');\n  angular.extend($root, this);\n  angular.forEach(angular.scenario.Runner.prototype, function(fn, name) {\n    $root[name] = angular.bind(self, fn);\n  });\n  $root.application = application;\n  $root.emit('RunnerBegin');\n  asyncForEach(this.rootDescribe.getSpecs(), function(spec, specDone) {\n    var dslCache = {};\n    var runner = self.createSpecRunner_($root);\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      dslCache[key] = fn.call($root);\n    });\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      self.$window[key] = function() {\n        var line = callerFile(3);\n        var scope = runner.$new();\n\n        // Make the dsl accessible on the current chain\n        scope.dsl = {};\n        angular.forEach(dslCache, function(fn, key) {\n          scope.dsl[key] = function() {\n            return dslCache[key].apply(scope, arguments);\n          };\n        });\n\n        // Make these methods work on the current chain\n        scope.addFuture = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFuture.apply(scope, arguments);\n        };\n        scope.addFutureAction = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFutureAction.apply(scope, arguments);\n        };\n\n        return scope.dsl[key].apply(scope, arguments);\n      };\n    });\n    runner.run(spec, function() {\n      runner.$destroy();\n      specDone.apply(this, arguments);\n    });\n  },\n  function(error) {\n    if (error) {\n      self.emit('RunnerError', error);\n    }\n    self.emit('RunnerEnd');\n  });\n};\n\n/**\n * This class is the \"this\" of the it/beforeEach/afterEach method.\n * Responsibilities:\n *   - \"this\" for it/beforeEach/afterEach\n *   - keep state for single it/beforeEach/afterEach execution\n *   - keep track of all of the futures to execute\n *   - run single spec (execute each future)\n */\nangular.scenario.SpecRunner = function() {\n  this.futures = [];\n  this.afterIndex = 0;\n};\n\n/**\n * Executes a spec which is an it block with associated before/after functions\n * based on the describe nesting.\n *\n * @param {Object} spec A spec object\n * @param {function()} specDone function that is called when the spec finshes. Function(error, index)\n */\nangular.scenario.SpecRunner.prototype.run = function(spec, specDone) {\n  var self = this;\n  this.spec = spec;\n\n  this.emit('SpecBegin', spec);\n\n  try {\n    spec.before.call(this);\n    spec.body.call(this);\n    this.afterIndex = this.futures.length;\n    spec.after.call(this);\n  } catch (e) {\n    this.emit('SpecError', spec, e);\n    this.emit('SpecEnd', spec);\n    specDone();\n    return;\n  }\n\n  var handleError = function(error, done) {\n    if (self.error) {\n      return done();\n    }\n    self.error = true;\n    done(null, self.afterIndex);\n  };\n\n  asyncForEach(\n    this.futures,\n    function(future, futureDone) {\n      self.step = future;\n      self.emit('StepBegin', spec, future);\n      try {\n        future.execute(function(error) {\n          if (error) {\n            self.emit('StepFailure', spec, future, error);\n            self.emit('StepEnd', spec, future);\n            return handleError(error, futureDone);\n          }\n          self.emit('StepEnd', spec, future);\n          self.$window.setTimeout(function() { futureDone(); }, 0);\n        });\n      } catch (e) {\n        self.emit('StepError', spec, future, e);\n        self.emit('StepEnd', spec, future);\n        handleError(e, futureDone);\n      }\n    },\n    function(e) {\n      if (e) {\n        self.emit('SpecError', spec, e);\n      }\n      self.emit('SpecEnd', spec);\n      // Call done in a timeout so exceptions don't recursively\n      // call this function\n      self.$window.setTimeout(function() { specDone(); }, 0);\n    }\n  );\n};\n\n/**\n * Adds a new future action.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFuture = function(name, behavior, line) {\n  var future = new angular.scenario.Future(name, angular.bind(this, behavior), line);\n  this.futures.push(future);\n  return future;\n};\n\n/**\n * Adds a new future action to be executed on the application window.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior, line) {\n  var self = this;\n  var NG = /\\[ng\\\\\\:/;\n  return this.addFuture(name, function(done) {\n    this.application.executeAction(function($window, $document) {\n\n      //TODO(esprehn): Refactor this so it doesn't need to be in here.\n      $document.elements = function(selector) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        selector = (self.selector || '') + ' ' + (selector || '');\n        selector = _jQuery.trim(selector) || '*';\n        angular.forEach(args, function(value, index) {\n          selector = selector.replace('$' + (index + 1), value);\n        });\n        var result = $document.find(selector);\n        if (selector.match(NG)) {\n          angular.forEach(['[ng-','[data-ng-','[x-ng-'], function(value, index){\n            result = result.add(selector.replace(NG, value), $document);\n          });\n        }\n        if (!result.length) {\n          throw {\n            type: 'selector',\n            message: 'Selector ' + selector + ' did not match any elements.'\n          };\n        }\n\n        return result;\n      };\n\n      try {\n        behavior.call(self, $window, $document, done);\n      } catch(e) {\n        if (e.type && e.type === 'selector') {\n          done(e.message);\n        } else {\n          throw e;\n        }\n      }\n    });\n  }, line);\n};\n\n/**\n * Shared DSL statements that are useful to all scenarios.\n */\n\n /**\n * Usage:\n *    pause() pauses until you call resume() in the console\n */\nangular.scenario.dsl('pause', function() {\n  return function() {\n    return this.addFuture('pausing for you to resume', function(done) {\n      this.emit('InteractivePause', this.spec, this.step);\n      this.$window.resume = function() { done(); };\n    });\n  };\n});\n\n/**\n * Usage:\n *    sleep(seconds) pauses the test for specified number of seconds\n */\nangular.scenario.dsl('sleep', function() {\n  return function(time) {\n    return this.addFuture('sleep for ' + time + ' seconds', function(done) {\n      this.$window.setTimeout(function() { done(null, time * 1000); }, time * 1000);\n    });\n  };\n});\n\n/**\n * Usage:\n *    browser().navigateTo(url) Loads the url into the frame\n *    browser().navigateTo(url, fn) where fn(url) is called and returns the URL to navigate to\n *    browser().reload() refresh the page (reload the same URL)\n *    browser().window.href() window.location.href\n *    browser().window.path() window.location.pathname\n *    browser().window.search() window.location.search\n *    browser().window.hash() window.location.hash without # prefix\n *    browser().location().url() see ng.$location#url\n *    browser().location().path() see ng.$location#path\n *    browser().location().search() see ng.$location#search\n *    browser().location().hash() see ng.$location#hash\n */\nangular.scenario.dsl('browser', function() {\n  var chain = {};\n\n  chain.navigateTo = function(url, delegate) {\n    var application = this.application;\n    return this.addFuture(\"browser navigate to '\" + url + \"'\", function(done) {\n      if (delegate) {\n        url = delegate.call(this, url);\n      }\n      application.navigateTo(url, function() {\n        done(null, url);\n      }, done);\n    });\n  };\n\n  chain.reload = function() {\n    var application = this.application;\n    return this.addFutureAction('browser reload', function($window, $document, done) {\n      var href = $window.location.href;\n      application.navigateTo(href, function() {\n        done(null, href);\n      }, done);\n    });\n  };\n\n  chain.window = function() {\n    var api = {};\n\n    api.href = function() {\n      return this.addFutureAction('window.location.href', function($window, $document, done) {\n        done(null, $window.location.href);\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('window.location.path', function($window, $document, done) {\n        done(null, $window.location.pathname);\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('window.location.search', function($window, $document, done) {\n        done(null, $window.location.search);\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('window.location.hash', function($window, $document, done) {\n        done(null, $window.location.hash.replace('#', ''));\n      });\n    };\n\n    return api;\n  };\n\n  chain.location = function() {\n    var api = {};\n\n    api.url = function() {\n      return this.addFutureAction('$location.url()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').url());\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('$location.path()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').path());\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('$location.search()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').search());\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('$location.hash()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').hash());\n      });\n    };\n\n    return api;\n  };\n\n  return function() {\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    expect(future).{matcher} where matcher is one of the matchers defined\n *    with angular.scenario.matcher\n *\n * ex. expect(binding(\"name\")).toEqual(\"Elliott\")\n */\nangular.scenario.dsl('expect', function() {\n  var chain = angular.extend({}, angular.scenario.matcher);\n\n  chain.not = function() {\n    this.inverse = true;\n    return chain;\n  };\n\n  return function(future) {\n    this.future = future;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    using(selector, label) scopes the next DSL element selection\n *\n * ex.\n *   using('#foo', \"'Foo' text field\").input('bar')\n */\nangular.scenario.dsl('using', function() {\n  return function(selector, label) {\n    this.selector = _jQuery.trim((this.selector||'') + ' ' + selector);\n    if (angular.isString(label) && label.length) {\n      this.label = label + ' ( ' + this.selector + ' )';\n    } else {\n      this.label = this.selector;\n    }\n    return this.dsl;\n  };\n});\n\n/**\n * Usage:\n *    binding(name) returns the value of the first matching binding\n */\nangular.scenario.dsl('binding', function() {\n  return function(name) {\n    return this.addFutureAction(\"select binding '\" + name + \"'\", function($window, $document, done) {\n      var values = $document.elements().bindings($window.angular.element, name);\n      if (!values.length) {\n        return done(\"Binding selector '\" + name + \"' did not match.\");\n      }\n      done(null, values[0]);\n    });\n  };\n});\n\n/**\n * Usage:\n *    input(name).enter(value) enters value in input with specified name\n *    input(name).check() checks checkbox\n *    input(name).select(value) selects the radio button with specified name/value\n *    input(name).val() returns the value of the input.\n */\nangular.scenario.dsl('input', function() {\n  var chain = {};\n  var supportInputEvent =  'oninput' in document.createElement('div') && msie != 9;\n\n  chain.enter = function(value, event) {\n    return this.addFutureAction(\"input '\" + this.name + \"' enter '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      input.val(value);\n      input.trigger(event || (supportInputEvent ? 'input' : 'change'));\n      done();\n    });\n  };\n\n  chain.check = function() {\n    return this.addFutureAction(\"checkbox '\" + this.name + \"' toggle\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':checkbox');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.select = function(value) {\n    return this.addFutureAction(\"radio button '\" + this.name + \"' toggle '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.\n        elements('[ng\\\\:model=\"$1\"][value=\"$2\"]', this.name, value).filter(':radio');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.val = function() {\n    return this.addFutureAction(\"return input val\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      done(null,input.val());\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n\n/**\n * Usage:\n *    repeater('#products table', 'Product List').count() number of rows\n *    repeater('#products table', 'Product List').row(1) all bindings in row as an array\n *    repeater('#products table', 'Product List').column('product.name') all values across all rows in an array\n */\nangular.scenario.dsl('repeater', function() {\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.column = function(binding) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' column '\" + binding + \"'\", function($window, $document, done) {\n      done(null, $document.elements().bindings($window.angular.element, binding));\n    });\n  };\n\n  chain.row = function(index) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' row '\" + index + \"'\", function($window, $document, done) {\n      var matches = $document.elements().slice(index, index + 1);\n      if (!matches.length)\n        return done('row ' + index + ' out of bounds');\n      done(null, matches.bindings($window.angular.element));\n    });\n  };\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    select(name).option('value') select one option\n *    select(name).options('value1', 'value2', ...) select options from a multi select\n */\nangular.scenario.dsl('select', function() {\n  var chain = {};\n\n  chain.option = function(value) {\n    return this.addFutureAction(\"select '\" + this.name + \"' option '\" + value + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[ng\\\\:model=\"$1\"]', this.name);\n      var option = select.find('option[value=\"' + value + '\"]');\n      if (option.length) {\n        select.val(value);\n      } else {\n        option = select.find('option:contains(\"' + value + '\")');\n        if (option.length) {\n          select.val(option.val());\n        }\n      }\n      select.trigger('change');\n      done();\n    });\n  };\n\n  chain.options = function() {\n    var values = arguments;\n    return this.addFutureAction(\"select '\" + this.name + \"' options '\" + values + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[multiple][ng\\\\:model=\"$1\"]', this.name);\n      select.val(values);\n      select.trigger('change');\n      done();\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    element(selector, label).count() get the number of elements that match selector\n *    element(selector, label).click() clicks an element\n *    element(selector, label).query(fn) executes fn(selectedElements, done)\n *    element(selector, label).{method}() gets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(value) sets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(key) gets the value (as defined by jQuery, ex. attr)\n *    element(selector, label).{method}(key, value) sets the value (as defined by jQuery, ex. attr)\n */\nangular.scenario.dsl('element', function() {\n  var KEY_VALUE_METHODS = ['attr', 'css', 'prop'];\n  var VALUE_METHODS = [\n    'val', 'text', 'html', 'height', 'innerHeight', 'outerHeight', 'width',\n    'innerWidth', 'outerWidth', 'position', 'scrollLeft', 'scrollTop', 'offset'\n  ];\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.click = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' click\", function($window, $document, done) {\n      var elements = $document.elements();\n      var href = elements.attr('href');\n      var eventProcessDefault = elements.trigger('click')[0];\n\n      if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {\n        this.application.navigateTo(href, function() {\n          done();\n        }, done);\n      } else {\n        done();\n      }\n    });\n  };\n\n  chain.query = function(fn) {\n    return this.addFutureAction('element ' + this.label + ' custom query', function($window, $document, done) {\n      fn.call(this, $document.elements(), done);\n    });\n  };\n\n  angular.forEach(KEY_VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(name, value) {\n      var args = arguments,\n          futureName = (args.length == 1)\n              ? \"element '\" + this.label + \"' get \" + methodName + \" '\" + name + \"'\"\n              : \"element '\" + this.label + \"' set \" + methodName + \" '\" + name + \"' to \" + \"'\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  angular.forEach(VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(value) {\n      var args = arguments,\n          futureName = (args.length == 0)\n              ? \"element '\" + this.label + \"' \" + methodName\n              : futureName = \"element '\" + this.label + \"' set \" + methodName + \" to '\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Matchers for implementing specs. Follows the Jasmine spec conventions.\n */\n\nangular.scenario.matcher('toEqual', function(expected) {\n  return angular.equals(this.actual, expected);\n});\n\nangular.scenario.matcher('toBe', function(expected) {\n  return this.actual === expected;\n});\n\nangular.scenario.matcher('toBeDefined', function() {\n  return angular.isDefined(this.actual);\n});\n\nangular.scenario.matcher('toBeTruthy', function() {\n  return this.actual;\n});\n\nangular.scenario.matcher('toBeFalsy', function() {\n  return !this.actual;\n});\n\nangular.scenario.matcher('toMatch', function(expected) {\n  return new RegExp(expected).test(this.actual);\n});\n\nangular.scenario.matcher('toBeNull', function() {\n  return this.actual === null;\n});\n\nangular.scenario.matcher('toContain', function(expected) {\n  return includes(this.actual, expected);\n});\n\nangular.scenario.matcher('toBeLessThan', function(expected) {\n  return this.actual < expected;\n});\n\nangular.scenario.matcher('toBeGreaterThan', function(expected) {\n  return this.actual > expected;\n});\n\n/**\n * User Interface for the Scenario Runner.\n *\n * TODO(esprehn): This should be refactored now that ObjectModel exists\n *  to use angular bindings for the UI.\n */\nangular.scenario.output('html', function(context, runner, model) {\n  var specUiMap = {},\n      lastStepUiMap = {};\n\n  context.append(\n    '<div id=\"header\">' +\n    '  <h1><span class=\"angular\">AngularJS</span>: Scenario Test Runner</h1>' +\n    '  <ul id=\"status-legend\" class=\"status-display\">' +\n    '    <li class=\"status-error\">0 Errors</li>' +\n    '    <li class=\"status-failure\">0 Failures</li>' +\n    '    <li class=\"status-success\">0 Passed</li>' +\n    '  </ul>' +\n    '</div>' +\n    '<div id=\"specs\">' +\n    '  <div class=\"test-children\"></div>' +\n    '</div>'\n  );\n\n  runner.on('InteractivePause', function(spec) {\n    var ui = lastStepUiMap[spec.id];\n    ui.find('.test-title').\n      html('paused... <a href=\"javascript:resume()\">resume</a> when ready.');\n  });\n\n  runner.on('SpecBegin', function(spec) {\n    var ui = findContext(spec);\n    ui.find('> .tests').append(\n      '<li class=\"status-pending test-it\"></li>'\n    );\n    ui = ui.find('> .tests li:last');\n    ui.append(\n      '<div class=\"test-info\">' +\n      '  <p class=\"test-title\">' +\n      '    <span class=\"timer-result\"></span>' +\n      '    <span class=\"test-name\"></span>' +\n      '  </p>' +\n      '</div>' +\n      '<div class=\"scrollpane\">' +\n      '  <ol class=\"test-actions\"></ol>' +\n      '</div>'\n    );\n    ui.find('> .test-info .test-name').text(spec.name);\n    ui.find('> .test-info').click(function() {\n      var scrollpane = ui.find('> .scrollpane');\n      var actions = scrollpane.find('> .test-actions');\n      var name = context.find('> .test-info .test-name');\n      if (actions.find(':visible').length) {\n        actions.hide();\n        name.removeClass('open').addClass('closed');\n      } else {\n        actions.show();\n        scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n        name.removeClass('closed').addClass('open');\n      }\n    });\n\n    specUiMap[spec.id] = ui;\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var ui = specUiMap[spec.id];\n    ui.append('<pre></pre>');\n    ui.find('> pre').text(formatException(error));\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    ui.removeClass('status-pending');\n    ui.addClass('status-' + spec.status);\n    ui.find(\"> .test-info .timer-result\").text(spec.duration + \"ms\");\n    if (spec.status === 'success') {\n      ui.find('> .test-info .test-name').addClass('closed');\n      ui.find('> .scrollpane .test-actions').hide();\n    }\n    updateTotals(spec.status);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    ui.find('> .scrollpane .test-actions').append('<li class=\"status-pending\"></li>');\n    var stepUi = lastStepUiMap[spec.id] = ui.find('> .scrollpane .test-actions li:last');\n    stepUi.append(\n      '<div class=\"timer-result\"></div>' +\n      '<div class=\"test-title\"></div>'\n    );\n    stepUi.find('> .test-title').text(step.name);\n    var scrollpane = stepUi.parents('.scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepEnd', function(spec, step) {\n    var stepUi = lastStepUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    stepUi.find('.timer-result').text(step.duration + 'ms');\n    stepUi.removeClass('status-pending');\n    stepUi.addClass('status-' + step.status);\n    var scrollpane = specUiMap[spec.id].find('> .scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  /**\n   * Finds the context of a spec block defined by the passed definition.\n   *\n   * @param {Object} The definition created by the Describe object.\n   */\n  function findContext(spec) {\n    var currentContext = context.find('#specs');\n    angular.forEach(model.getDefinitionPath(spec), function(defn) {\n      var id = 'describe-' + defn.id;\n      if (!context.find('#' + id).length) {\n        currentContext.find('> .test-children').append(\n          '<div class=\"test-describe\" id=\"' + id + '\">' +\n          '  <h2></h2>' +\n          '  <div class=\"test-children\"></div>' +\n          '  <ul class=\"tests\"></ul>' +\n          '</div>'\n        );\n        context.find('#' + id).find('> h2').text('describe: ' + defn.name);\n      }\n      currentContext = context.find('#' + id);\n    });\n    return context.find('#describe-' + spec.definition.id);\n  }\n\n  /**\n   * Updates the test counter for the status.\n   *\n   * @param {string} the status.\n   */\n  function updateTotals(status) {\n    var legend = context.find('#status-legend .status-' + status);\n    var parts = legend.text().split(' ');\n    var value = (parts[0] * 1) + 1;\n    legend.text(value + ' ' + parts[1]);\n  }\n\n  /**\n   * Add an error to a step.\n   *\n   * @param {Object} The JQuery wrapped context\n   * @param {function()} fn() that should return the file/line number of the error\n   * @param {Object} the error.\n   */\n  function addError(context, line, error) {\n    context.find('.test-title').append('<pre></pre>');\n    var message = _jQuery.trim(line() + '\\n\\n' + formatException(error));\n    context.find('.test-title pre:last').text(message);\n  }\n});\n\n/**\n * Generates JSON output into a context.\n */\nangular.scenario.output('json', function(context, runner, model) {\n  model.on('RunnerEnd', function() {\n    context.text(angular.toJson(model.value));\n  });\n});\n\n/**\n * Generates XML output into a context.\n */\nangular.scenario.output('xml', function(context, runner, model) {\n  var $ = function(args) {return new context.init(args);};\n  model.on('RunnerEnd', function() {\n    var scenario = $('<scenario></scenario>');\n    context.append(scenario);\n    serializeXml(scenario, model.value);\n  });\n\n  /**\n   * Convert the tree into XML.\n   *\n   * @param {Object} context jQuery context to add the XML to.\n   * @param {Object} tree node to serialize\n   */\n  function serializeXml(context, tree) {\n     angular.forEach(tree.children, function(child) {\n       var describeContext = $('<describe></describe>');\n       describeContext.attr('id', child.id);\n       describeContext.attr('name', child.name);\n       context.append(describeContext);\n       serializeXml(describeContext, child);\n     });\n     var its = $('<its></its>');\n     context.append(its);\n     angular.forEach(tree.specs, function(spec) {\n       var it = $('<it></it>');\n       it.attr('id', spec.id);\n       it.attr('name', spec.name);\n       it.attr('duration', spec.duration);\n       it.attr('status', spec.status);\n       its.append(it);\n       angular.forEach(spec.steps, function(step) {\n         var stepContext = $('<step></step>');\n         stepContext.attr('name', step.name);\n         stepContext.attr('duration', step.duration);\n         stepContext.attr('status', step.status);\n         it.append(stepContext);\n         if (step.error) {\n           var error = $('<error></error>');\n           stepContext.append(error);\n           error.text(formatException(stepContext.error));\n         }\n       });\n     });\n   }\n});\n\n/**\n * Creates a global value $result with the result of the runner.\n */\nangular.scenario.output('object', function(context, runner, model) {\n  runner.$window.$result = model.value;\n});\nbindJQuery();\npublishExternalAPI(angular);\n\nvar $runner = new angular.scenario.Runner(window),\n    scripts = document.getElementsByTagName('script'),\n    script = scripts[scripts.length - 1],\n    config = {};\n\nangular.forEach(script.attributes, function(attr) {\n  var match = attr.name.match(/ng[:\\-](.*)/);\n  if (match) {\n    config[match[1]] = attr.value || true;\n  }\n});\n\nif (config.autotest) {\n  JQLite(document).ready(function() {\n    angular.scenario.setUpAndRun(config);\n  });\n}\n})(window, document);\n\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n\\n[ng\\\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\\n.ng-cloak, .x-ng-cloak {\\n  display: none;\\n}\\n\\nng\\\\:form {\\n  display: block;\\n}\\n</style>');\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n/* CSS Document */\\n\\n/** Structure */\\nbody {\\n  font-family: Arial, sans-serif;\\n  margin: 0;\\n  font-size: 14px;\\n}\\n\\n#system-error {\\n  font-size: 1.5em;\\n  text-align: center;\\n}\\n\\n#json, #xml {\\n  display: none;\\n}\\n\\n#header {\\n  position: fixed;\\n  width: 100%;\\n}\\n\\n#specs {\\n  padding-top: 50px;\\n}\\n\\n#header .angular {\\n  font-family: Courier New, monospace;\\n  font-weight: bold;\\n}\\n\\n#header h1 {\\n  font-weight: normal;\\n  float: left;\\n  font-size: 30px;\\n  line-height: 30px;\\n  margin: 0;\\n  padding: 10px 10px;\\n  height: 30px;\\n}\\n\\n#application h2,\\n#specs h2 {\\n  margin: 0;\\n  padding: 0.5em;\\n  font-size: 1.1em;\\n}\\n\\n#status-legend {\\n  margin-top: 10px;\\n  margin-right: 10px;\\n}\\n\\n#header,\\n#application,\\n.test-info,\\n.test-actions li {\\n  overflow: hidden;\\n}\\n\\n#application {\\n  margin: 10px;\\n}\\n\\n#application iframe {\\n  width: 100%;\\n  height: 758px;\\n}\\n\\n#application .popout {\\n  float: right;\\n}\\n\\n#application iframe {\\n  border: none;\\n}\\n\\n.tests li,\\n.test-actions li,\\n.test-it li,\\n.test-it ol,\\n.status-display {\\n  list-style-type: none;\\n}\\n\\n.tests,\\n.test-it ol,\\n.status-display {\\n  margin: 0;\\n  padding: 0;\\n}\\n\\n.test-info {\\n  margin-left: 1em;\\n  margin-top: 0.5em;\\n  border-radius: 8px 0 0 8px;\\n  -webkit-border-radius: 8px 0 0 8px;\\n  -moz-border-radius: 8px 0 0 8px;\\n  cursor: pointer;\\n}\\n\\n.test-info:hover .test-name {\\n  text-decoration: underline;\\n}\\n\\n.test-info .closed:before {\\n  content: \\'\\\\25b8\\\\00A0\\';\\n}\\n\\n.test-info .open:before {\\n  content: \\'\\\\25be\\\\00A0\\';\\n  font-weight: bold;\\n}\\n\\n.test-it ol {\\n  margin-left: 2.5em;\\n}\\n\\n.status-display,\\n.status-display li {\\n  float: right;\\n}\\n\\n.status-display li {\\n  padding: 5px 10px;\\n}\\n\\n.timer-result,\\n.test-title {\\n  display: inline-block;\\n  margin: 0;\\n  padding: 4px;\\n}\\n\\n.test-actions .test-title,\\n.test-actions .test-result {\\n  display: table-cell;\\n  padding-left: 0.5em;\\n  padding-right: 0.5em;\\n}\\n\\n.test-actions {\\n  display: table;\\n}\\n\\n.test-actions li {\\n  display: table-row;\\n}\\n\\n.timer-result {\\n  width: 4em;\\n  padding: 0 10px;\\n  text-align: right;\\n  font-family: monospace;\\n}\\n\\n.test-it pre,\\n.test-actions pre {\\n  clear: left;\\n  color: black;\\n  margin-left: 6em;\\n}\\n\\n.test-describe {\\n  padding-bottom: 0.5em;\\n}\\n\\n.test-describe .test-describe {\\n  margin: 5px 5px 10px 2em;\\n}\\n\\n.test-actions .status-pending .test-title:before {\\n  content: \\'\\\\00bb\\\\00A0\\';\\n}\\n\\n.scrollpane {\\n   max-height: 20em;\\n   overflow: auto;\\n}\\n\\n/** Colors */\\n\\n#header {\\n  background-color: #F2C200;\\n}\\n\\n#specs h2 {\\n  border-top: 2px solid #BABAD1;\\n}\\n\\n#specs h2,\\n#application h2 {\\n  background-color: #efefef;\\n}\\n\\n#application {\\n  border: 1px solid #BABAD1;\\n}\\n\\n.test-describe .test-describe {\\n  border-left: 1px solid #BABAD1;\\n  border-right: 1px solid #BABAD1;\\n  border-bottom: 1px solid #BABAD1;\\n}\\n\\n.status-display {\\n  border: 1px solid #777;\\n}\\n\\n.status-display .status-pending,\\n.status-pending .test-info {\\n  background-color: #F9EEBC;\\n}\\n\\n.status-display .status-success,\\n.status-success .test-info {\\n  background-color: #B1D7A1;\\n}\\n\\n.status-display .status-failure,\\n.status-failure .test-info {\\n  background-color: #FF8286;\\n}\\n\\n.status-display .status-error,\\n.status-error .test-info {\\n  background-color: black;\\n  color: white;\\n}\\n\\n.test-actions .status-success .test-title {\\n  color: #30B30A;\\n}\\n\\n.test-actions .status-failure .test-title {\\n  color: #DF0000;\\n}\\n\\n.test-actions .status-error .test-title {\\n  color: black;\\n}\\n\\n.test-actions .timer-result {\\n  color: #888;\\n}\\n</style>');"
  },
  {
    "path": "chapter5/recipe4/test/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter5/recipe4/test/unit/controllersSpec.js",
    "content": "'use strict';\n\n/* jasmine specs for controllers go here */\n\ndescribe('MyCtrl', function(){\n  var scope, ctrl;\n\n  beforeEach(inject(function($injector, $controller, $rootScope) {  \n    scope = $rootScope.$new();\n    ctrl = $controller(MyCtrl, { $scope: scope });\n  }));\n\n  it('should change greeting value if name value is changed', function() {\n    scope.name = \"Frederik\";\n    scope.$digest();\n    expect(scope.greeting).toBe(\"Greetings Frederik\");\n  });\n});"
  },
  {
    "path": "chapter5/recipe5/README.md",
    "content": "# angular-seed — the seed for AngularJS apps\n\nThis project is an application skeleton for a typical [AngularJS](http://angularjs.org/) web app.\nYou can use it to quickly bootstrap your angular webapp projects and dev environment for these\nprojects.\n\nThe seed contains AngularJS libraries, test libraries and a bunch of scripts all preconfigured for\ninstant web development gratification. Just clone the repo (or download the zip/tarball), start up\nour (or yours) webserver and you are ready to develop and test your application.\n\nThe seed app doesn't do much, just shows how to wire two controllers and views together. You can\ncheck it out by opening app/index.html in your browser (might not work file `file://` scheme in\ncertain browsers, see note below).\n\n_Note: While angular is client-side-only technology and it's possible to create angular webapps that\ndon't require a backend server at all, we recommend hosting the project files using a local\nwebserver during development to avoid issues with security restrictions (sandbox) in browsers. The\nsandbox implementation varies between browsers, but quite often prevents things like cookies, xhr,\netc to function properly when an html page is opened via `file://` scheme instead of `http://`._\n\n\n## How to use angular-seed\n\nClone the angular-seed repository and start hacking...\n\n\n### Running the app during development\n\nYou can pick one of these options:\n\n* serve this repository with your webserver\n* install node.js and run `scripts/web-server.js`\n\nThen navigate your browser to `http://localhost:<port>/app/index.html` to see the app running in\nyour browser.\n\n\n### Running the app in production\n\nThis really depends on how complex is your app and the overall infrastructure of your system, but\nthe general rule is that all you need in production are all the files under the `app/` directory.\nEverything else should be omitted.\n\nAngular apps are really just a bunch of static html, css and js files that just need to be hosted\nsomewhere, where they can be accessed by browsers.\n\nIf your Angular app is talking to the backend server via xhr or other means, you need to figure\nout what is the best way to host the static files to comply with the same origin policy if\napplicable. Usually this is done by hosting the files by the backend server or through\nreverse-proxying the backend server(s) and a webserver(s).\n\n\n### Running unit tests\n\nWe recommend using [jasmine](http://pivotal.github.com/jasmine/) and\n[Testacular](http://vojtajina.github.com/testacular/) for your unit tests/specs, but you are free\nto use whatever works for you.\n\nRequires [node.js](http://nodejs.org/), Testacular (`sudo npm install -g testacular`) and a local\nor remote browser.\n\n* start `scripts/test.sh` (on windows: `scripts\\test.bat`)\n  * a browser will start and connect to the Testacular server (Chrome is default browser, others can be captured by loading the same url as the one in Chrome or by changing the `config/testacular.conf.js` file)\n* to run or re-run tests just change any of your source or test javascript files\n\n\n### End to end testing\n\nAngular ships with a baked-in end-to-end test runner that understands angular, your app and allows\nyou to write your tests with jasmine-like BDD syntax.\n\nRequires a webserver, node.js + `./scripts/web-server.js` or your backend server that hosts the angular static files.\n\nCheck out the\n[end-to-end runner's documentation](http://docs.angularjs.org/guide/dev_guide.e2e-testing) for more\ninfo.\n\n* create your end-to-end tests in `test/e2e/scenarios.js`\n* serve your project directory with your http/backend server or node.js + `scripts/web-server.js`\n* to run do one of:\n  * open `http://localhost:port/test/e2e/runner.html` in your browser\n  * run the tests from console with [Testacular](vojtajina.github.com/testacular) via\n    `scripts/e2e-test.sh` or `script/e2e-test.bat`\n\n\n### Receiving updates from upstream\n\nWhen we upgrade angular-seed's repo with newer angular or testing library code, you can just\nfetch the changes and merge them into your project with git.\n\n\n## Directory Layout\n\n    app/                --> all of the files to be used in production\n      css/              --> css files\n        app.css         --> default stylesheet\n      img/              --> image files\n      index.html        --> app layout file (the main html template file of the app)\n      index-async.html  --> just like index.html, but loads js files asynchronously\n      js/               --> javascript files\n        app.js          --> application\n        controllers.js  --> application controllers\n        directives.js   --> application directives\n        filters.js      --> custom angular filters\n        services.js     --> custom angular services\n      lib/              --> angular and 3rd party javascript libraries\n        angular/\n          angular.js        --> the latest angular js\n          angular.min.js    --> the latest minified angular js\n          angular-*.js      --> angular add-on modules\n          version.txt       --> version number\n      partials/             --> angular view partials (partial html templates)\n        partial1.html\n        partial2.html\n\n    config/testacular.conf.js        --> config file for running unit tests with Testacular\n    config/testacular-e2e.conf.js    --> config file for running e2e tests with Testacular\n\n    scripts/            --> handy shell/js/ruby scripts\n      e2e-test.sh       --> runs end-to-end tests with Testacular (*nix)\n      e2e-test.bat      --> runs end-to-end tests with Testacular (windows)\n      test.bat          --> autotests unit tests with Testacular (windows)\n      test.sh           --> autotests unit tests with Testacular (*nix)\n      web-server.js     --> simple development webserver based on node.js\n\n    test/               --> test source files and libraries\n      e2e/              -->\n        runner.html     --> end-to-end test runner (open in your browser to run)\n        scenarios.js    --> end-to-end specs\n      lib/\n        angular/                --> angular testing libraries\n          angular-mocks.js      --> mocks that replace certain angular services in tests\n          angular-scenario.js   --> angular's scenario (end-to-end) test runner library\n          version.txt           --> version file\n      unit/                     --> unit level specs/tests\n        controllersSpec.js      --> specs for controllers\n        directivessSpec.js      --> specs for directives\n        filtersSpec.js          --> specs for filters\n        servicesSpec.js         --> specs for services\n\n## Contact\n\nFor more information on AngularJS please check out http://angularjs.org/\n"
  },
  {
    "path": "chapter5/recipe5/app/css/.gitignore",
    "content": ""
  },
  {
    "path": "chapter5/recipe5/app/css/app.css",
    "content": "/* app css stylesheet */\n\n.menu {\n  list-style: none;\n  border-bottom: 0.1em solid black;\n  margin-bottom: 2em;\n  padding: 0 0 0.5em;\n}\n\n.menu:before {\n  content: \"[\";\n}\n\n.menu:after {\n  content: \"]\";\n}\n\n.menu > li {\n  display: inline;\n}\n\n.menu > li:before {\n  content: \"|\";\n  padding-right: 0.3em;\n}\n\n.menu > li:nth-child(1):before {\n  content: \"\";\n  padding: 0;\n}\n"
  },
  {
    "path": "chapter5/recipe5/app/img/.gitignore",
    "content": ""
  },
  {
    "path": "chapter5/recipe5/app/index-async.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <style>\n    [ng-cloak] {\n      display: none;\n    }\n  </style>\n  <script>\n    // include angular loader, which allows the files to load in any order\n    /*\n     AngularJS v1.0.0rc1\n     (c) 2010-2012 AngularJS http://angularjs.org\n     License: MIT\n    */\n    'use strict';(function(i){function d(c,a,e){return c[a]||(c[a]=e())}return d(d(i,\"angular\",Object),\"module\",function(){var c={};return function(a,e,f){e&&c.hasOwnProperty(a)&&(c[a]=null);return d(c,a,function(){function b(a,b,d){return function(){c[d||\"push\"]([a,b,arguments]);return g}}if(!e)throw Error(\"No module: \"+a);var c=[],d=[],h=b(\"$injector\",\"invoke\"),g={_invokeQueue:c,_runBlocks:d,requires:e,name:a,provider:b(\"$provide\",\"provider\"),factory:b(\"$provide\",\"factory\"),service:b(\"$provide\",\"service\"),\n    value:b(\"$provide\",\"value\"),constant:b(\"$provide\",\"constant\",\"unshift\"),filter:b(\"$filterProvider\",\"register\"),directive:b(\"$compileProvider\",\"directive\"),config:h,run:function(a){d.push(a);return this}};f&&h(f);return g})}})})(window);\n\n    // include a third-party async loader library\n    /*!\n     * $script.js v1.3\n     * https://github.com/ded/script.js\n     * Copyright: @ded & @fat - Dustin Diaz, Jacob Thornton 2011\n     * Follow our software http://twitter.com/dedfat\n     * License: MIT\n     */\n    !function(a,b,c){function t(a,c){var e=b.createElement(\"script\"),f=j;e.onload=e.onerror=e[o]=function(){e[m]&&!/^c|loade/.test(e[m])||f||(e.onload=e[o]=null,f=1,c())},e.async=1,e.src=a,d.insertBefore(e,d.firstChild)}function q(a,b){p(a,function(a){return!b(a)})}var d=b.getElementsByTagName(\"head\")[0],e={},f={},g={},h={},i=\"string\",j=!1,k=\"push\",l=\"DOMContentLoaded\",m=\"readyState\",n=\"addEventListener\",o=\"onreadystatechange\",p=function(a,b){for(var c=0,d=a.length;c<d;++c)if(!b(a[c]))return j;return 1};!b[m]&&b[n]&&(b[n](l,function r(){b.removeEventListener(l,r,j),b[m]=\"complete\"},j),b[m]=\"loading\");var s=function(a,b,d){function o(){if(!--m){e[l]=1,j&&j();for(var a in g)p(a.split(\"|\"),n)&&!q(g[a],n)&&(g[a]=[])}}function n(a){return a.call?a():e[a]}a=a[k]?a:[a];var i=b&&b.call,j=i?b:d,l=i?a.join(\"\"):b,m=a.length;c(function(){q(a,function(a){h[a]?(l&&(f[l]=1),o()):(h[a]=1,l&&(f[l]=1),t(s.path?s.path+a+\".js\":a,o))})},0);return s};s.get=t,s.ready=function(a,b,c){a=a[k]?a:[a];var d=[];!q(a,function(a){e[a]||d[k](a)})&&p(a,function(a){return e[a]})?b():!function(a){g[a]=g[a]||[],g[a][k](b),c&&c(d)}(a.join(\"|\"));return s};var u=a.$script;s.noConflict=function(){a.$script=u;return this},typeof module!=\"undefined\"&&module.exports?module.exports=s:a.$script=s}(this,document,setTimeout)\n\n    // load all of the dependencies asynchronously.\n    $script([\n      'lib/angular/angular.js',\n      'js/app.js',\n      'js/services.js',\n      'js/controllers.js',\n      'js/filters.js',\n      'js/directives.js'\n    ], function() {\n      // when all is done, execute bootstrap angular application\n      angular.bootstrap(document, ['myApp']);\n    });\n  </script>\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\">\n</head>\n<body ng-cloak>\n  <ul class=\"menu\">\n    <li><a href=\"#/view1\">view1</a></li>\n    <li><a href=\"#/view2\">view2</a></li>\n  </ul>\n\n  <div ng-view></div>\n\n  <div>Angular seed app: v<span app-version></span></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "chapter5/recipe5/app/index.html",
    "content": "<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\"/>\n</head>\n<body ng-app=\"MyApp\">\n  <div ng-controller=\"MyCtrl\">\n    <input type=\"text\" ng-model=\"searchTerm\" placeholder=\"Search term\">\n    <button ng-click=\"search()\">Search</button>\n    <ul ng-repeat=\"tweet in searchResult.results\">\n      <li>{{tweet.text}}</li>\n    </ul>\n  </div>  \n\n  <script src=\"lib/angular/angular.js\"></script>\n  <script src=\"lib/angular/angular-resource.js\"></script>\n  <script src=\"js/controllers.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "chapter5/recipe5/app/js/controllers.js",
    "content": "var app = angular.module(\"MyApp\", [\"ngResource\"]);\n\napp.factory(\"TwitterAPI\", function($resource) {\n  return $resource(\"http://search.twitter.com/search.json\",\n    { callback: \"JSON_CALLBACK\" },\n    { get: { method: \"JSONP\" }});\n});\n\napp.controller(\"MyCtrl\", function($scope, TwitterAPI) {\n  $scope.search = function() {\n    $scope.searchResult = TwitterAPI.get({ q: $scope.searchTerm });\n  };\n});"
  },
  {
    "path": "chapter5/recipe5/app/lib/angular/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngCookies\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookies\n   * @requires $browser\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from\n   * this object, new cookies are created/deleted at the end of current $eval.\n   *\n   * @example\n   */\n   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for(name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            if (angular.isDefined(lastCookies[name])) {\n              cookies[name] = lastCookies[name];\n            } else {\n              delete cookies[name];\n            }\n          } else if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated){\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   * @example\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#get\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          return angular.fromJson($cookies[key]);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#put\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#remove\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter5/recipe5/app/lib/angular/angular-loader.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n\n(\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n'use strict';\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n)(window);\n\n/**\n * Closure compiler type information\n *\n * @typedef { {\n *   requires: !Array.<string>,\n *   invokeQueue: !Array.<Array.<*>>,\n *\n *   service: function(string, Function):angular.Module,\n *   factory: function(string, Function):angular.Module,\n *   value: function(string, *):angular.Module,\n *\n *   filter: function(string, Function):angular.Module,\n *\n *   init: function(Function):angular.Module\n * } }\n */\nangular.Module;\n\n"
  },
  {
    "path": "chapter5/recipe5/app/lib/angular/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g. \n *   `http://example.com:8080/api`), you'll need to escape the colon character before the port\n *   number, like this: `$resource('http://example.com\\\\:8080/api')`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` – {string} – The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` – {object=} – Optional set of pre-bound parameters for this action.\n *   - isArray – {boolean=} – If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n     * encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace((pctEncodeSpaces ? null : /%20/g), '+');\n    }\n\n    function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        action.method = angular.uppercase(action.method);\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter5/recipe5/app/lib/angular/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             '<p style=\"color:blue\">an html\\n' +\n             '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n             'snippet</p>';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n          Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n           <table>\n             <tr>\n               <td>Filter</td>\n               <td>Source</td>\n               <td>Rendered</td>\n             </tr>\n             <tr id=\"html-filter\">\n               <td>html filter</td>\n               <td>\n                 <pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre>\n               </td>\n               <td>\n                 <div ng-bind-html=\"snippet\"></div>\n               </td>\n             </tr>\n             <tr id=\"escaped-html\">\n               <td>no filter</td>\n               <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind=\"snippet\"></div></td>\n             </tr>\n             <tr id=\"html-unsafe-filter\">\n               <td>unsafe html filter</td>\n               <td><pre>&lt;div ng-bind-html-unsafe=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind-html-unsafe=\"snippet\"></div></td>\n             </tr>\n           </table>\n         </div>\n     </doc:source>\n     <doc:scenario>\n       it('should sanitize the html snippet ', function() {\n         expect(using('#html-filter').element('div').html()).\n           toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n       });\n\n       it('should escape snippet without any filter', function() {\n         expect(using('#escaped-html').element('div').html()).\n           toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n                \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n                \"snippet&lt;/p&gt;\");\n       });\n\n       it('should inline raw snippet if filtered as unsafe', function() {\n         expect(using('#html-unsafe-filter').element(\"div\").html()).\n           toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n                \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n                \"snippet</p>\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new <b>text</b>');\n         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');\n         expect(using('#escaped-html').element('div').html()).toBe(\"new &lt;b&gt;text&lt;/b&gt;\");\n         expect(using('#html-unsafe-filter').binding(\"snippet\")).toBe('new <b>text</b>');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar $sanitize = function(html) {\n  var buf = [];\n    htmlParser(html, htmlSanitizeWriter(buf));\n    return buf.join('');\n};\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP = /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  URI_REGEXP = /^((ftp|https?):\\/\\/|mailto:|#)/,\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g; // Match everything outside of normal chars and \" (quote character)\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,aside,\" +\n        \"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,\" +\n        \"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,bdi,bdo,\" +\n        \"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,\" +\n        \"span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        index = html.indexOf(\"-->\");\n\n        if ( index >= 0 ) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'), function(all, text){\n        text = text.\n          replace(COMMENT_REGEXP, \"$1\").\n          replace(CDATA_REGEXP, \"$1\");\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n\n        return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw \"Parse Error: \" + html;\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {\n      var value = doubleQuotedValue\n        || singleQoutedValue\n        || unqoutedValue\n        || '';\n\n      attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nvar hiddenPre=document.createElement(\"pre\");\nfunction decodeEntities(value) {\n  hiddenPre.innerHTML=value.replace(/</g,\"&lt;\");\n  return hiddenPre.innerText || hiddenPre.textContent || '';\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] == true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] == true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).value('$sanitize', $sanitize);\n\n/**\n * @ngdoc directive\n * @name ngSanitize.directive:ngBindHtml\n *\n * @description\n * Creates a binding that will sanitize the result of evaluating the `expression` with the\n * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n */\nangular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);\n    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {\n      value = $sanitize(value);\n      element.html(value || '');\n    });\n  };\n}]);\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n *   plain email address links.\n *\n * @param {string} text Input text.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should linkify the snippet with urls', function() {\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('Pretty text with some links:&#10;' +\n                '<a href=\"http://angularjs.org/\">http://angularjs.org/</a>,&#10;' +\n                '<a href=\"mailto:us@somewhere.org\">us@somewhere.org</a>,&#10;' +\n                '<a href=\"mailto:another@somewhere.org\">another@somewhere.org</a>,&#10;' +\n                'and one more: <a href=\"ftp://127.0.0.1/\">ftp://127.0.0.1/</a>.');\n       });\n\n       it ('should not linkify snippet without the linky filter', function() {\n         expect(using('#escaped-html').binding('snippet')).\n           toBe(\"Pretty text with some links:\\n\" +\n                \"http://angularjs.org/,\\n\" +\n                \"mailto:us@somewhere.org,\\n\" +\n                \"another@somewhere.org,\\n\" +\n                \"and one more: ftp://127.0.0.1/.\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new http://link.');\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('new <a href=\"http://link\">http://link</a>.');\n         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', function() {\n  var LINKY_URL_REGEXP = /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s\\.\\;\\,\\(\\)\\{\\}\\<\\>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    // TODO(vojta): use $sanitize instead\n    var writer = htmlSanitizeWriter(html);\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      writer.chars(raw.substr(0, i));\n      writer.start('a', {href:url});\n      writer.chars(match[0].replace(MAILTO_REGEXP, ''));\n      writer.end('a');\n      raw = raw.substring(i + match[0].length);\n    }\n    writer.chars(raw);\n    return html.join('');\n  };\n});\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter5/recipe5/app/lib/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter5/recipe5/app/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter5/recipe5/config/testacular-e2e.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  ANGULAR_SCENARIO,\n  ANGULAR_SCENARIO_ADAPTER,\n  'test/e2e/**/*.js'\n];\n\nautoWatch = false;\n\nbrowsers = ['Chrome'];\n\nsingleRun = true;\n\nproxies = {\n  '/': 'http://localhost:8000/'\n};\n\njunitReporter = {\n  outputFile: 'test_out/e2e.xml',\n  suite: 'e2e'\n};\n"
  },
  {
    "path": "chapter5/recipe5/config/testacular.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  JASMINE,\n  JASMINE_ADAPTER,\n  'app/lib/angular/angular.js',\n  'app/lib/angular/angular-*.js',\n  'test/lib/angular/angular-mocks.js',\n  'app/js/**/*.js',\n  'test/unit/**/*.js'\n];\n\nautoWatch = true;\n\nbrowsers = ['Chrome'];\n\njunitReporter = {\n  outputFile: 'test_out/unit.xml',\n  suite: 'unit'\n};\n"
  },
  {
    "path": "chapter5/recipe5/logs/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "chapter5/recipe5/scripts/e2e-test.bat",
    "content": "@echo off\n\nREM Windows script for running e2e tests\nREM You have to run server and capture some browser first\nREM\nREM Requirements:\nREM - NodeJS (http://nodejs.org/)\nREM - Testacular (npm install -g testacular)\n\nset BASE_DIR=%~dp0\ntestacular start \"%BASE_DIR%\\..\\config\\testacular-e2e.conf.js\" %*\n"
  },
  {
    "path": "chapter5/recipe5/scripts/e2e-test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular-e2e.conf.js $*\n"
  },
  {
    "path": "chapter5/recipe5/scripts/test.bat",
    "content": "@echo off\r\n\r\nREM Windows script for running unit tests\r\nREM You have to run server and capture some browser first\r\nREM\r\nREM Requirements:\r\nREM - NodeJS (http://nodejs.org/)\r\nREM - Testacular (npm install -g testacular)\r\n\r\nset BASE_DIR=%~dp0\r\ntestacular start \"%BASE_DIR%\\..\\config\\testacular.conf.js\" %*\r\n"
  },
  {
    "path": "chapter5/recipe5/scripts/test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular.conf.js $*\n"
  },
  {
    "path": "chapter5/recipe5/scripts/watchr.rb",
    "content": "#!/usr/bin/env watchr\n\n# config file for watchr http://github.com/mynyml/watchr\n# install: gem install watchr\n# run: watch watchr.rb\n# note: make sure that you have jstd server running (server.sh) and a browser captured\n\nlog_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log')\n\n`cd ..`\n`touch #{log_file}`\n\nputs \"String watchr... log file: #{log_file}\"\n\nwatch( '(app/js|test/unit)' )  do\n  `echo \"\\n\\ntest run started @ \\`date\\`\" > #{log_file}`\n  `scripts/test.sh &> #{log_file}`\nend\n\n"
  },
  {
    "path": "chapter5/recipe5/scripts/web-server.js",
    "content": "#!/usr/bin/env node\n\nvar util = require('util'),\n    http = require('http'),\n    fs = require('fs'),\n    url = require('url'),\n    events = require('events');\n\nvar DEFAULT_PORT = 8000;\n\nfunction main(argv) {\n  new HttpServer({\n    'GET': createServlet(StaticServlet),\n    'HEAD': createServlet(StaticServlet)\n  }).start(Number(argv[2]) || DEFAULT_PORT);\n}\n\nfunction escapeHtml(value) {\n  return value.toString().\n    replace('<', '&lt;').\n    replace('>', '&gt;').\n    replace('\"', '&quot;');\n}\n\nfunction createServlet(Class) {\n  var servlet = new Class();\n  return servlet.handleRequest.bind(servlet);\n}\n\n/**\n * An Http server implementation that uses a map of methods to decide\n * action routing.\n *\n * @param {Object} Map of method => Handler function\n */\nfunction HttpServer(handlers) {\n  this.handlers = handlers;\n  this.server = http.createServer(this.handleRequest_.bind(this));\n}\n\nHttpServer.prototype.start = function(port) {\n  this.port = port;\n  this.server.listen(port);\n  util.puts('Http Server running at http://localhost:' + port + '/');\n};\n\nHttpServer.prototype.parseUrl_ = function(urlString) {\n  var parsed = url.parse(urlString);\n  parsed.pathname = url.resolve('/', parsed.pathname);\n  return url.parse(url.format(parsed), true);\n};\n\nHttpServer.prototype.handleRequest_ = function(req, res) {\n  var logEntry = req.method + ' ' + req.url;\n  if (req.headers['user-agent']) {\n    logEntry += ' ' + req.headers['user-agent'];\n  }\n  util.puts(logEntry);\n  req.url = this.parseUrl_(req.url);\n  var handler = this.handlers[req.method];\n  if (!handler) {\n    res.writeHead(501);\n    res.end();\n  } else {\n    handler.call(this, req, res);\n  }\n};\n\n/**\n * Handles static content.\n */\nfunction StaticServlet() {}\n\nStaticServlet.MimeMap = {\n  'txt': 'text/plain',\n  'html': 'text/html',\n  'css': 'text/css',\n  'xml': 'application/xml',\n  'json': 'application/json',\n  'js': 'application/javascript',\n  'jpg': 'image/jpeg',\n  'jpeg': 'image/jpeg',\n  'gif': 'image/gif',\n  'png': 'image/png',\n  'svg': 'image/svg+xml'\n};\n\nStaticServlet.prototype.handleRequest = function(req, res) {\n  var self = this;\n  var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){\n    return String.fromCharCode(parseInt(hex, 16));\n  });\n  var parts = path.split('/');\n  if (parts[parts.length-1].charAt(0) === '.')\n    return self.sendForbidden_(req, res, path);\n  fs.stat(path, function(err, stat) {\n    if (err)\n      return self.sendMissing_(req, res, path);\n    if (stat.isDirectory())\n      return self.sendDirectory_(req, res, path);\n    return self.sendFile_(req, res, path);\n  });\n}\n\nStaticServlet.prototype.sendError_ = function(req, res, error) {\n  res.writeHead(500, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>Internal Server Error</title>\\n');\n  res.write('<h1>Internal Server Error</h1>');\n  res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');\n  util.puts('500 Internal Server Error');\n  util.puts(util.inspect(error));\n};\n\nStaticServlet.prototype.sendMissing_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(404, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>404 Not Found</title>\\n');\n  res.write('<h1>Not Found</h1>');\n  res.write(\n    '<p>The requested URL ' +\n    escapeHtml(path) +\n    ' was not found on this server.</p>'\n  );\n  res.end();\n  util.puts('404 Not Found: ' + path);\n};\n\nStaticServlet.prototype.sendForbidden_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(403, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>403 Forbidden</title>\\n');\n  res.write('<h1>Forbidden</h1>');\n  res.write(\n    '<p>You do not have permission to access ' +\n    escapeHtml(path) + ' on this server.</p>'\n  );\n  res.end();\n  util.puts('403 Forbidden: ' + path);\n};\n\nStaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {\n  res.writeHead(301, {\n      'Content-Type': 'text/html',\n      'Location': redirectUrl\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>301 Moved Permanently</title>\\n');\n  res.write('<h1>Moved Permanently</h1>');\n  res.write(\n    '<p>The document has moved <a href=\"' +\n    redirectUrl +\n    '\">here</a>.</p>'\n  );\n  res.end();\n  util.puts('301 Moved Permanently: ' + redirectUrl);\n};\n\nStaticServlet.prototype.sendFile_ = function(req, res, path) {\n  var self = this;\n  var file = fs.createReadStream(path);\n  res.writeHead(200, {\n    'Content-Type': StaticServlet.\n      MimeMap[path.split('.').pop()] || 'text/plain'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n  } else {\n    file.on('data', res.write.bind(res));\n    file.on('close', function() {\n      res.end();\n    });\n    file.on('error', function(error) {\n      self.sendError_(req, res, error);\n    });\n  }\n};\n\nStaticServlet.prototype.sendDirectory_ = function(req, res, path) {\n  var self = this;\n  if (path.match(/[^\\/]$/)) {\n    req.url.pathname += '/';\n    var redirectUrl = url.format(url.parse(url.format(req.url)));\n    return self.sendRedirect_(req, res, redirectUrl);\n  }\n  fs.readdir(path, function(err, files) {\n    if (err)\n      return self.sendError_(req, res, error);\n\n    if (!files.length)\n      return self.writeDirectoryIndex_(req, res, path, []);\n\n    var remaining = files.length;\n    files.forEach(function(fileName, index) {\n      fs.stat(path + '/' + fileName, function(err, stat) {\n        if (err)\n          return self.sendError_(req, res, err);\n        if (stat.isDirectory()) {\n          files[index] = fileName + '/';\n        }\n        if (!(--remaining))\n          return self.writeDirectoryIndex_(req, res, path, files);\n      });\n    });\n  });\n};\n\nStaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {\n  path = path.substring(1);\n  res.writeHead(200, {\n    'Content-Type': 'text/html'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n    return;\n  }\n  res.write('<!doctype html>\\n');\n  res.write('<title>' + escapeHtml(path) + '</title>\\n');\n  res.write('<style>\\n');\n  res.write('  ol { list-style-type: none; font-size: 1.2em; }\\n');\n  res.write('</style>\\n');\n  res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');\n  res.write('<ol>');\n  files.forEach(function(fileName) {\n    if (fileName.charAt(0) !== '.') {\n      res.write('<li><a href=\"' +\n        escapeHtml(fileName) + '\">' +\n        escapeHtml(fileName) + '</a></li>');\n    }\n  });\n  res.write('</ol>');\n  res.end();\n};\n\n// Must be last,\nmain(process.argv);\n"
  },
  {
    "path": "chapter5/recipe5/test/e2e/runner.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <title>End2end Test Runner</title>\n    <script src=\"../lib/angular/angular-scenario.js\" ng-autotest></script>\n    <script src=\"scenarios.js\"></script>\n  </head>\n  <body>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter5/recipe5/test/e2e/scenarios.js",
    "content": "'use strict';\n\n/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */\n\ndescribe('my app', function() {\n\n  beforeEach(function() {\n    browser().navigateTo('../../app/index.html');\n  });\n\n\n  it('should automatically redirect to /view1 when location hash/fragment is empty', function() {\n    expect(browser().location().url()).toBe(\"/view1\");\n  });\n\n\n  describe('view1', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view1');\n    });\n\n\n    it('should render view1 when user navigates to /view1', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 1/);\n    });\n\n  });\n\n\n  describe('view2', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view2');\n    });\n\n\n    it('should render view2 when user navigates to /view2', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 2/);\n    });\n\n  });\n});\n"
  },
  {
    "path": "chapter5/recipe5/test/lib/angular/angular-mocks.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n *\n * TODO(vojta): wrap whole file into closure during build\n */\n\n/**\n * @ngdoc overview\n * @name angular.mock\n * @description\n *\n * Namespace from 'angular-mocks.js' which contains testing related code.\n */\nangular.mock = {};\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ngMock.$browser\n *\n * @description\n * This service is a mock implementation of {@link ng.$browser}. It provides fake\n * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,\n * cookies, etc...\n *\n * The api of this service is the same as that of the real {@link ng.$browser $browser}, except\n * that there are several helper methods available which can be used in tests.\n */\nangular.mock.$BrowserProvider = function() {\n  this.$get = function(){\n    return new angular.mock.$Browser();\n  };\n};\n\nangular.mock.$Browser = function() {\n  var self = this;\n\n  this.isMock = true;\n  self.$$url = \"http://server/\";\n  self.$$lastUrl = self.$$url; // used by url polling fn\n  self.pollFns = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = angular.noop;\n  self.$$incOutstandingRequestCount = angular.noop;\n\n\n  // register url polling fn\n\n  self.onUrlChange = function(listener) {\n    self.pollFns.push(\n      function() {\n        if (self.$$lastUrl != self.$$url) {\n          self.$$lastUrl = self.$$url;\n          listener(self.$$url);\n        }\n      }\n    );\n\n    return listener;\n  };\n\n  self.cookieHash = {};\n  self.lastCookieHash = {};\n  self.deferredFns = [];\n  self.deferredNextId = 0;\n\n  self.defer = function(fn, delay) {\n    delay = delay || 0;\n    self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});\n    self.deferredFns.sort(function(a,b){ return a.time - b.time;});\n    return self.deferredNextId++;\n  };\n\n\n  self.defer.now = 0;\n\n\n  self.defer.cancel = function(deferId) {\n    var fnIndex;\n\n    angular.forEach(self.deferredFns, function(fn, index) {\n      if (fn.id === deferId) fnIndex = index;\n    });\n\n    if (fnIndex !== undefined) {\n      self.deferredFns.splice(fnIndex, 1);\n      return true;\n    }\n\n    return false;\n  };\n\n\n  /**\n   * @name ngMock.$browser#defer.flush\n   * @methodOf ngMock.$browser\n   *\n   * @description\n   * Flushes all pending requests and executes the defer callbacks.\n   *\n   * @param {number=} number of milliseconds to flush. See {@link #defer.now}\n   */\n  self.defer.flush = function(delay) {\n    if (angular.isDefined(delay)) {\n      self.defer.now += delay;\n    } else {\n      if (self.deferredFns.length) {\n        self.defer.now = self.deferredFns[self.deferredFns.length-1].time;\n      } else {\n        throw Error('No deferred tasks to be flushed');\n      }\n    }\n\n    while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {\n      self.deferredFns.shift().fn();\n    }\n  };\n  /**\n   * @name ngMock.$browser#defer.now\n   * @propertyOf ngMock.$browser\n   *\n   * @description\n   * Current milliseconds mock time.\n   */\n\n  self.$$baseHref = '';\n  self.baseHref = function() {\n    return this.$$baseHref;\n  };\n};\nangular.mock.$Browser.prototype = {\n\n/**\n  * @name ngMock.$browser#poll\n  * @methodOf ngMock.$browser\n  *\n  * @description\n  * run all fns in pollFns\n  */\n  poll: function poll() {\n    angular.forEach(this.pollFns, function(pollFn){\n      pollFn();\n    });\n  },\n\n  addPollFn: function(pollFn) {\n    this.pollFns.push(pollFn);\n    return pollFn;\n  },\n\n  url: function(url, replace) {\n    if (url) {\n      this.$$url = url;\n      return this;\n    }\n\n    return this.$$url;\n  },\n\n  cookies:  function(name, value) {\n    if (name) {\n      if (value == undefined) {\n        delete this.cookieHash[name];\n      } else {\n        if (angular.isString(value) &&       //strings only\n            value.length <= 4096) {          //strict cookie storage limits\n          this.cookieHash[name] = value;\n        }\n      }\n    } else {\n      if (!angular.equals(this.cookieHash, this.lastCookieHash)) {\n        this.lastCookieHash = angular.copy(this.cookieHash);\n        this.cookieHash = angular.copy(this.cookieHash);\n      }\n      return this.cookieHash;\n    }\n  },\n\n  notifyWhenNoOutstandingRequests: function(fn) {\n    fn();\n  }\n};\n\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandlerProvider\n *\n * @description\n * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed\n * into the `$exceptionHandler`.\n */\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandler\n *\n * @description\n * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed\n * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration\n * information.\n *\n *\n * <pre>\n *   describe('$exceptionHandlerProvider', function() {\n *\n *     it('should capture log messages and exceptions', function() {\n *\n *       module(function($exceptionHandlerProvider) {\n *         $exceptionHandlerProvider.mode('log');\n *       });\n *\n *       inject(function($log, $exceptionHandler, $timeout) {\n *         $timeout(function() { $log.log(1); });\n *         $timeout(function() { $log.log(2); throw 'banana peel'; });\n *         $timeout(function() { $log.log(3); });\n *         expect($exceptionHandler.errors).toEqual([]);\n *         expect($log.assertEmpty());\n *         $timeout.flush();\n *         expect($exceptionHandler.errors).toEqual(['banana peel']);\n *         expect($log.log.logs).toEqual([[1], [2], [3]]);\n *       });\n *     });\n *   });\n * </pre>\n */\n\nangular.mock.$ExceptionHandlerProvider = function() {\n  var handler;\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$exceptionHandlerProvider#mode\n   * @methodOf ngMock.$exceptionHandlerProvider\n   *\n   * @description\n   * Sets the logging mode.\n   *\n   * @param {string} mode Mode of operation, defaults to `rethrow`.\n   *\n   *   - `rethrow`: If any errors are are passed into the handler in tests, it typically\n   *                means that there is a bug in the application or test, so this mock will\n   *                make these tests fail.\n   *   - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores an\n   *            array of errors in `$exceptionHandler.errors`, to allow later assertion of them.\n   *            See {@link ngMock.$log#assertEmpty assertEmpty()} and\n   *             {@link ngMock.$log#reset reset()}\n   */\n  this.mode = function(mode) {\n    switch(mode) {\n      case 'rethrow':\n        handler = function(e) {\n          throw e;\n        };\n        break;\n      case 'log':\n        var errors = [];\n\n        handler = function(e) {\n          if (arguments.length == 1) {\n            errors.push(e);\n          } else {\n            errors.push([].slice.call(arguments, 0));\n          }\n        };\n\n        handler.errors = errors;\n        break;\n      default:\n        throw Error(\"Unknown mode '\" + mode + \"', only 'log'/'rethrow' modes are allowed!\");\n    }\n  };\n\n  this.$get = function() {\n    return handler;\n  };\n\n  this.mode('rethrow');\n};\n\n\n/**\n * @ngdoc service\n * @name ngMock.$log\n *\n * @description\n * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays\n * (one array per logging level). These arrays are exposed as `logs` property of each of the\n * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.\n *\n */\nangular.mock.$LogProvider = function() {\n\n  function concat(array1, array2, index) {\n    return array1.concat(Array.prototype.slice.call(array2, index));\n  }\n\n\n  this.$get = function () {\n    var $log = {\n      log: function() { $log.log.logs.push(concat([], arguments, 0)); },\n      warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },\n      info: function() { $log.info.logs.push(concat([], arguments, 0)); },\n      error: function() { $log.error.logs.push(concat([], arguments, 0)); }\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#reset\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Reset all of the logging arrays to empty.\n     */\n    $log.reset = function () {\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#log.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.log.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#warn.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.warn.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#info.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.info.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#error.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.error.logs = [];\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#assertEmpty\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.\n     */\n    $log.assertEmpty = function() {\n      var errors = [];\n      angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {\n        angular.forEach($log[logLevel].logs, function(log) {\n          angular.forEach(log, function (logItem) {\n            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\\n' + (logItem.stack || ''));\n          });\n        });\n      });\n      if (errors.length) {\n        errors.unshift(\"Expected $log to be empty! Either a message was logged unexpectedly, or an expected \" +\n          \"log message was not checked and removed:\");\n        errors.push('');\n        throw new Error(errors.join('\\n---------\\n'));\n      }\n    };\n\n    $log.reset();\n    return $log;\n  };\n};\n\n\n(function() {\n  var R_ISO8061_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?:\\:?(\\d\\d)(?:\\:?(\\d\\d)(?:\\.(\\d{3}))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d)))?$/;\n\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8061_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n  function int(str) {\n    return parseInt(str, 10);\n  }\n\n  function padNumber(num, digits, trim) {\n    var neg = '';\n    if (num < 0) {\n      neg =  '-';\n      num = -num;\n    }\n    num = '' + num;\n    while(num.length < digits) num = '0' + num;\n    if (trim)\n      num = num.substr(num.length - digits);\n    return neg + num;\n  }\n\n\n  /**\n   * @ngdoc object\n   * @name angular.mock.TzDate\n   * @description\n   *\n   * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.\n   *\n   * Mock of the Date type which has its timezone specified via constroctor arg.\n   *\n   * The main purpose is to create Date-like instances with timezone fixed to the specified timezone\n   * offset, so that we can test code that depends on local timezone settings without dependency on\n   * the time zone settings of the machine where the code is running.\n   *\n   * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)\n   * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*\n   *\n   * @example\n   * !!!! WARNING !!!!!\n   * This is not a complete Date object so only methods that were implemented can be called safely.\n   * To make matters worse, TzDate instances inherit stuff from Date via a prototype.\n   *\n   * We do our best to intercept calls to \"unimplemented\" methods, but since the list of methods is\n   * incomplete we might be missing some non-standard methods. This can result in errors like:\n   * \"Date.prototype.foo called on incompatible Object\".\n   *\n   * <pre>\n   * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');\n   * newYearInBratislava.getTimezoneOffset() => -60;\n   * newYearInBratislava.getFullYear() => 2010;\n   * newYearInBratislava.getMonth() => 0;\n   * newYearInBratislava.getDate() => 1;\n   * newYearInBratislava.getHours() => 0;\n   * newYearInBratislava.getMinutes() => 0;\n   * </pre>\n   *\n   */\n  angular.mock.TzDate = function (offset, timestamp) {\n    var self = new Date(0);\n    if (angular.isString(timestamp)) {\n      var tsStr = timestamp;\n\n      self.origDate = jsonStringToDate(timestamp);\n\n      timestamp = self.origDate.getTime();\n      if (isNaN(timestamp))\n        throw {\n          name: \"Illegal Argument\",\n          message: \"Arg '\" + tsStr + \"' passed into TzDate constructor is not a valid date string\"\n        };\n    } else {\n      self.origDate = new Date(timestamp);\n    }\n\n    var localOffset = new Date(timestamp).getTimezoneOffset();\n    self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;\n    self.date = new Date(timestamp + self.offsetDiff);\n\n    self.getTime = function() {\n      return self.date.getTime() - self.offsetDiff;\n    };\n\n    self.toLocaleDateString = function() {\n      return self.date.toLocaleDateString();\n    };\n\n    self.getFullYear = function() {\n      return self.date.getFullYear();\n    };\n\n    self.getMonth = function() {\n      return self.date.getMonth();\n    };\n\n    self.getDate = function() {\n      return self.date.getDate();\n    };\n\n    self.getHours = function() {\n      return self.date.getHours();\n    };\n\n    self.getMinutes = function() {\n      return self.date.getMinutes();\n    };\n\n    self.getSeconds = function() {\n      return self.date.getSeconds();\n    };\n\n    self.getTimezoneOffset = function() {\n      return offset * 60;\n    };\n\n    self.getUTCFullYear = function() {\n      return self.origDate.getUTCFullYear();\n    };\n\n    self.getUTCMonth = function() {\n      return self.origDate.getUTCMonth();\n    };\n\n    self.getUTCDate = function() {\n      return self.origDate.getUTCDate();\n    };\n\n    self.getUTCHours = function() {\n      return self.origDate.getUTCHours();\n    };\n\n    self.getUTCMinutes = function() {\n      return self.origDate.getUTCMinutes();\n    };\n\n    self.getUTCSeconds = function() {\n      return self.origDate.getUTCSeconds();\n    };\n\n    self.getUTCMilliseconds = function() {\n      return self.origDate.getUTCMilliseconds();\n    };\n\n    self.getDay = function() {\n      return self.date.getDay();\n    };\n\n    // provide this method only on browsers that already have it\n    if (self.toISOString) {\n      self.toISOString = function() {\n        return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +\n              padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +\n              padNumber(self.origDate.getUTCDate(), 2) + 'T' +\n              padNumber(self.origDate.getUTCHours(), 2) + ':' +\n              padNumber(self.origDate.getUTCMinutes(), 2) + ':' +\n              padNumber(self.origDate.getUTCSeconds(), 2) + '.' +\n              padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'\n      }\n    }\n\n    //hide all methods not implemented in this mock that the Date prototype exposes\n    var unimplementedMethods = ['getMilliseconds', 'getUTCDay',\n        'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',\n        'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',\n        'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',\n        'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',\n        'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];\n\n    angular.forEach(unimplementedMethods, function(methodName) {\n      self[methodName] = function() {\n        throw Error(\"Method '\" + methodName + \"' is not implemented in the TzDate mock\");\n      };\n    });\n\n    return self;\n  };\n\n  //make \"tzDateInstance instanceof Date\" return true\n  angular.mock.TzDate.prototype = Date.prototype;\n})();\n\n\n/**\n * @ngdoc function\n * @name angular.mock.dump\n * @description\n *\n * *NOTE*: this is not an injectable instance, just a globally available function.\n *\n * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.\n *\n * This method is also available on window, where it can be used to display objects on debug console.\n *\n * @param {*} object - any object to turn into string.\n * @return {string} a serialized string of the argument\n */\nangular.mock.dump = function(object) {\n  return serialize(object);\n\n  function serialize(object) {\n    var out;\n\n    if (angular.isElement(object)) {\n      object = angular.element(object);\n      out = angular.element('<div></div>');\n      angular.forEach(object, function(element) {\n        out.append(angular.element(element).clone());\n      });\n      out = out.html();\n    } else if (angular.isArray(object)) {\n      out = [];\n      angular.forEach(object, function(o) {\n        out.push(serialize(o));\n      });\n      out = '[ ' + out.join(', ') + ' ]';\n    } else if (angular.isObject(object)) {\n      if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {\n        out = serializeScope(object);\n      } else if (object instanceof Error) {\n        out = object.stack || ('' + object.name + ': ' + object.message);\n      } else {\n        out = angular.toJson(object, true);\n      }\n    } else {\n      out = String(object);\n    }\n\n    return out;\n  }\n\n  function serializeScope(scope, offset) {\n    offset = offset ||  '  ';\n    var log = [offset + 'Scope(' + scope.$id + '): {'];\n    for ( var key in scope ) {\n      if (scope.hasOwnProperty(key) && !key.match(/^(\\$|this)/)) {\n        log.push('  ' + key + ': ' + angular.toJson(scope[key]));\n      }\n    }\n    var child = scope.$$childHead;\n    while(child) {\n      log.push(serializeScope(child, offset + '  '));\n      child = child.$$nextSibling;\n    }\n    log.push('}');\n    return log.join('\\n' + offset);\n  }\n};\n\n/**\n * @ngdoc object\n * @name ngMock.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for unit testing application that use the\n * {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less\n * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.\n *\n * During unit testing, we want our unit tests to run quickly and have no external dependencies so\n * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or\n * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is\n * to verify whether a certain request has been sent or not, or alternatively just let the\n * application make requests, respond with pre-trained responses and assert that the end result is\n * what we expect it to be.\n *\n * This mock implementation can be used to respond with static or dynamic responses via the\n * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).\n *\n * When an Angular application needs some data from a server, it calls the $http service, which\n * sends the request to a real server using $httpBackend service. With dependency injection, it is\n * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify\n * the requests and respond with some testing data without sending a request to real server.\n *\n * There are two ways to specify what test data should be returned as http responses by the mock\n * backend when the code under test makes http requests:\n *\n * - `$httpBackend.expect` - specifies a request expectation\n * - `$httpBackend.when` - specifies a backend definition\n *\n *\n * # Request Expectations vs Backend Definitions\n *\n * Request expectations provide a way to make assertions about requests made by the application and\n * to define responses for those requests. The test will fail if the expected requests are not made\n * or they are made in the wrong order.\n *\n * Backend definitions allow you to define a fake backend for your application which doesn't assert\n * if a particular request was made or not, it just returns a trained response if a request is made.\n * The test will pass whether or not the request gets made during testing.\n *\n *\n * <table class=\"table\">\n *   <tr><th width=\"220px\"></th><th>Request expectations</th><th>Backend definitions</th></tr>\n *   <tr>\n *     <th>Syntax</th>\n *     <td>.expect(...).respond(...)</td>\n *     <td>.when(...).respond(...)</td>\n *   </tr>\n *   <tr>\n *     <th>Typical usage</th>\n *     <td>strict unit tests</td>\n *     <td>loose (black-box) unit testing</td>\n *   </tr>\n *   <tr>\n *     <th>Fulfills multiple requests</th>\n *     <td>NO</td>\n *     <td>YES</td>\n *   </tr>\n *   <tr>\n *     <th>Order of requests matters</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Request required</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Response required</th>\n *     <td>optional (see below)</td>\n *     <td>YES</td>\n *   </tr>\n * </table>\n *\n * In cases where both backend definitions and request expectations are specified during unit\n * testing, the request expectations are evaluated first.\n *\n * If a request expectation has no response specified, the algorithm will search your backend\n * definitions for an appropriate response.\n *\n * If a request didn't match any expectation or if the expectation doesn't have the response\n * defined, the backend definitions are evaluated in sequential order to see if any of them match\n * the request. The response from the first matched definition is returned.\n *\n *\n * # Flushing HTTP requests\n *\n * The $httpBackend used in production, always responds to requests with responses asynchronously.\n * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are\n * hard to write, follow and maintain. At the same time the testing mock, can't respond\n * synchronously because that would change the execution of the code under test. For this reason the\n * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending\n * requests and thus preserving the async api of the backend, while allowing the test to execute\n * synchronously.\n *\n *\n * # Unit testing with mock $httpBackend\n *\n * <pre>\n   // controller\n   function MyController($scope, $http) {\n     $http.get('/auth.py').success(function(data) {\n       $scope.user = data;\n     });\n\n     this.saveMessage = function(message) {\n       $scope.status = 'Saving...';\n       $http.post('/add-msg.py', message).success(function(response) {\n         $scope.status = '';\n       }).error(function() {\n         $scope.status = 'ERROR!';\n       });\n     };\n   }\n\n   // testing controller\n   var $httpBackend;\n\n   beforeEach(inject(function($injector) {\n     $httpBackend = $injector.get('$httpBackend');\n\n     // backend definition common for all tests\n     $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});\n   }));\n\n\n   afterEach(function() {\n     $httpBackend.verifyNoOutstandingExpectation();\n     $httpBackend.verifyNoOutstandingRequest();\n   });\n\n\n   it('should fetch authentication token', function() {\n     $httpBackend.expectGET('/auth.py');\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n   });\n\n\n   it('should send msg to server', function() {\n     // now you don’t care about the authentication, but\n     // the controller will still send the request and\n     // $httpBackend will respond without you having to\n     // specify the expectation and response for this request\n     $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');\n\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n     controller.saveMessage('message content');\n     expect(controller.status).toBe('Saving...');\n     $httpBackend.flush();\n     expect(controller.status).toBe('');\n   });\n\n\n   it('should send auth header', function() {\n     $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {\n       // check if the header was send, if it wasn't the expectation won't\n       // match the request and the test will fail\n       return headers['Authorization'] == 'xxx';\n     }).respond(201, '');\n\n     var controller = scope.$new(MyController);\n     controller.saveMessage('whatever');\n     $httpBackend.flush();\n   });\n   </pre>\n */\nangular.mock.$HttpBackendProvider = function() {\n  this.$get = [createHttpBackendMock];\n};\n\n/**\n * General factory function for $httpBackend mock.\n * Returns instance for unit testing (when no arguments specified):\n *   - passing through is disabled\n *   - auto flushing is disabled\n *\n * Returns instance for e2e testing (when `$delegate` and `$browser` specified):\n *   - passing through (delegating request to real backend) is enabled\n *   - auto flushing is enabled\n *\n * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)\n * @param {Object=} $browser Auto-flushing enabled if specified\n * @return {Object} Instance of $httpBackend mock\n */\nfunction createHttpBackendMock($delegate, $browser) {\n  var definitions = [],\n      expectations = [],\n      responses = [],\n      responsesPush = angular.bind(responses, responses.push);\n\n  function createResponse(status, data, headers) {\n    if (angular.isFunction(status)) return status;\n\n    return function() {\n      return angular.isNumber(status)\n          ? [status, data, headers]\n          : [200, status, data];\n    };\n  }\n\n  // TODO(vojta): change params to: method, url, data, headers, callback\n  function $httpBackend(method, url, data, callback, headers) {\n    var xhr = new MockXhr(),\n        expectation = expectations[0],\n        wasExpected = false;\n\n    function prettyPrint(data) {\n      return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)\n          ? data\n          : angular.toJson(data);\n    }\n\n    if (expectation && expectation.match(method, url)) {\n      if (!expectation.matchData(data))\n        throw Error('Expected ' + expectation + ' with different data\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.data) + '\\nGOT:      ' + data);\n\n      if (!expectation.matchHeaders(headers))\n        throw Error('Expected ' + expectation + ' with different headers\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.headers) + '\\nGOT:      ' +\n            prettyPrint(headers));\n\n      expectations.shift();\n\n      if (expectation.response) {\n        responses.push(function() {\n          var response = expectation.response(method, url, data, headers);\n          xhr.$$respHeaders = response[2];\n          callback(response[0], response[1], xhr.getAllResponseHeaders());\n        });\n        return;\n      }\n      wasExpected = true;\n    }\n\n    var i = -1, definition;\n    while ((definition = definitions[++i])) {\n      if (definition.match(method, url, data, headers || {})) {\n        if (definition.response) {\n          // if $browser specified, we do auto flush all requests\n          ($browser ? $browser.defer : responsesPush)(function() {\n            var response = definition.response(method, url, data, headers);\n            xhr.$$respHeaders = response[2];\n            callback(response[0], response[1], xhr.getAllResponseHeaders());\n          });\n        } else if (definition.passThrough) {\n          $delegate(method, url, data, callback, headers);\n        } else throw Error('No response defined !');\n        return;\n      }\n    }\n    throw wasExpected ?\n        Error('No response defined !') :\n        Error('Unexpected request: ' + method + ' ' + url + '\\n' +\n              (expectation ? 'Expected ' + expectation : 'No more request expected'));\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#when\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current definition.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.when = function(method, url, data, headers) {\n    var definition = new MockHttpExpectation(method, url, data, headers),\n        chain = {\n          respond: function(status, data, headers) {\n            definition.response = createResponse(status, data, headers);\n          }\n        };\n\n    if ($browser) {\n      chain.passThrough = function() {\n        definition.passThrough = true;\n      };\n    }\n\n    definitions.push(definition);\n    return chain;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for GET requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for HEAD requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for DELETE requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for POST requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for PUT requests.  For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for JSONP requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n  createShortMethods('when');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expect\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current expectation.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *  request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.expect = function(method, url, data, headers) {\n    var expectation = new MockHttpExpectation(method, url, data, headers);\n    expectations.push(expectation);\n    return {\n      respond: function(status, data, headers) {\n        expectation.response = createResponse(status, data, headers);\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for GET requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled. See #expect for more info.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for HEAD requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for DELETE requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for POST requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PUT requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPATCH\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PATCH requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for JSONP requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n  createShortMethods('expect');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#flush\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Flushes all pending requests using the trained responses.\n   *\n   * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,\n   *   all pending requests will be flushed. If there are no pending requests when the flush method\n   *   is called an exception is thrown (as this typically a sign of programming error).\n   */\n  $httpBackend.flush = function(count) {\n    if (!responses.length) throw Error('No pending request to flush !');\n\n    if (angular.isDefined(count)) {\n      while (count--) {\n        if (!responses.length) throw Error('No more pending request to flush !');\n        responses.shift()();\n      }\n    } else {\n      while (responses.length) {\n        responses.shift()();\n      }\n    }\n    $httpBackend.verifyNoOutstandingExpectation();\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingExpectation\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that all of the requests defined via the `expect` api were made. If any of the\n   * requests were not made, verifyNoOutstandingExpectation throws an exception.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyExpectations);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingExpectation = function() {\n    if (expectations.length) {\n      throw Error('Unsatisfied requests: ' + expectations.join(', '));\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingRequest\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that there are no outstanding requests that need to be flushed.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyNoOutstandingRequest);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingRequest = function() {\n    if (responses.length) {\n      throw Error('Unflushed requests: ' + responses.length);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#resetExpectations\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Resets all request expectations, but preserves all backend definitions. Typically, you would\n   * call resetExpectations during a multiple-phase test when you want to reuse the same instance of\n   * $httpBackend mock.\n   */\n  $httpBackend.resetExpectations = function() {\n    expectations.length = 0;\n    responses.length = 0;\n  };\n\n  return $httpBackend;\n\n\n  function createShortMethods(prefix) {\n    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {\n     $httpBackend[prefix + method] = function(url, headers) {\n       return $httpBackend[prefix](method, url, undefined, headers)\n     }\n    });\n\n    angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {\n      $httpBackend[prefix + method] = function(url, data, headers) {\n        return $httpBackend[prefix](method, url, data, headers)\n      }\n    });\n  }\n}\n\nfunction MockHttpExpectation(method, url, data, headers) {\n\n  this.data = data;\n  this.headers = headers;\n\n  this.match = function(m, u, d, h) {\n    if (method != m) return false;\n    if (!this.matchUrl(u)) return false;\n    if (angular.isDefined(d) && !this.matchData(d)) return false;\n    if (angular.isDefined(h) && !this.matchHeaders(h)) return false;\n    return true;\n  };\n\n  this.matchUrl = function(u) {\n    if (!url) return true;\n    if (angular.isFunction(url.test)) return url.test(u);\n    return url == u;\n  };\n\n  this.matchHeaders = function(h) {\n    if (angular.isUndefined(headers)) return true;\n    if (angular.isFunction(headers)) return headers(h);\n    return angular.equals(headers, h);\n  };\n\n  this.matchData = function(d) {\n    if (angular.isUndefined(data)) return true;\n    if (data && angular.isFunction(data.test)) return data.test(d);\n    if (data && !angular.isString(data)) return angular.toJson(data) == d;\n    return data == d;\n  };\n\n  this.toString = function() {\n    return method + ' ' + url;\n  };\n}\n\nfunction MockXhr() {\n\n  // hack for testing $http, $httpBackend\n  MockXhr.$$lastInstance = this;\n\n  this.open = function(method, url, async) {\n    this.$$method = method;\n    this.$$url = url;\n    this.$$async = async;\n    this.$$reqHeaders = {};\n    this.$$respHeaders = {};\n  };\n\n  this.send = function(data) {\n    this.$$data = data;\n  };\n\n  this.setRequestHeader = function(key, value) {\n    this.$$reqHeaders[key] = value;\n  };\n\n  this.getResponseHeader = function(name) {\n    // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last\n    var header = this.$$respHeaders[name];\n    if (header) return header;\n\n    name = angular.lowercase(name);\n    header = this.$$respHeaders[name];\n    if (header) return header;\n\n    header = undefined;\n    angular.forEach(this.$$respHeaders, function(headerVal, headerName) {\n      if (!header && angular.lowercase(headerName) == name) header = headerVal;\n    });\n    return header;\n  };\n\n  this.getAllResponseHeaders = function() {\n    var lines = [];\n\n    angular.forEach(this.$$respHeaders, function(value, key) {\n      lines.push(key + ': ' + value);\n    });\n    return lines.join('\\n');\n  };\n\n  this.abort = angular.noop;\n}\n\n\n/**\n * @ngdoc function\n * @name ngMock.$timeout\n * @description\n *\n * This service is just a simple decorator for {@link ng.$timeout $timeout} service\n * that adds a \"flush\" method.\n */\n\n/**\n * @ngdoc method\n * @name ngMock.$timeout#flush\n * @methodOf ngMock.$timeout\n * @description\n *\n * Flushes the queue of pending tasks.\n */\n\n/**\n *\n */\nangular.mock.$RootElementProvider = function() {\n  this.$get = function() {\n    return angular.element('<div ng-app></div>');\n  }\n};\n\n/**\n * @ngdoc overview\n * @name ngMock\n * @description\n *\n * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful\n * mocks to the {@link AUTO.$injector $injector}.\n */\nangular.module('ngMock', ['ng']).provider({\n  $browser: angular.mock.$BrowserProvider,\n  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,\n  $log: angular.mock.$LogProvider,\n  $httpBackend: angular.mock.$HttpBackendProvider,\n  $rootElement: angular.mock.$RootElementProvider\n}).config(function($provide) {\n  $provide.decorator('$timeout', function($delegate, $browser) {\n    $delegate.flush = function() {\n      $browser.defer.flush();\n    };\n    return $delegate;\n  });\n});\n\n\n/**\n * @ngdoc overview\n * @name ngMockE2E\n * @description\n *\n * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.\n * Currently there is only one mock present in this module -\n * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.\n */\nangular.module('ngMockE2E', ['ng']).config(function($provide) {\n  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);\n});\n\n/**\n * @ngdoc object\n * @name ngMockE2E.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of\n * applications that use the {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for unit testing please see\n * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.\n *\n * This implementation can be used to respond with static or dynamic responses via the `when` api\n * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the\n * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch\n * templates from a webserver).\n *\n * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application\n * is being developed with the real backend api replaced with a mock, it is often desirable for\n * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch\n * templates or static files from the webserver). To configure the backend with this behavior\n * use the `passThrough` request handler of `when` instead of `respond`.\n *\n * Additionally, we don't want to manually have to flush mocked out requests like we do during unit\n * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests\n * automatically, closely simulating the behavior of the XMLHttpRequest object.\n *\n * To setup the application to run with this http backend, you have to create a module that depends\n * on the `ngMockE2E` and your application modules and defines the fake backend:\n *\n * <pre>\n *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);\n *   myAppDev.run(function($httpBackend) {\n *     phones = [{name: 'phone1'}, {name: 'phone2'}];\n *\n *     // returns the current list of phones\n *     $httpBackend.whenGET('/phones').respond(phones);\n *\n *     // adds a new phone to the phones array\n *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {\n *       phones.push(angular.fromJSON(data));\n *     });\n *     $httpBackend.whenGET(/^\\/templates\\//).passThrough();\n *     //...\n *   });\n * </pre>\n *\n * Afterwards, bootstrap your app with this new module.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#when\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition.\n *\n * @param {string} method HTTP method.\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n *   object and returns true if the headers match the current definition.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n *\n *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n *    – The respond method takes a set of static data to be returned or a function that can return\n *    an array containing response status (number), response data (string) and response headers\n *    (Object).\n *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`\n *    handler, will be pass through to the real backend (an XHR request will be made to the\n *    server.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenGET\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for GET requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenHEAD\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for HEAD requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenDELETE\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for DELETE requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPOST\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for POST requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPUT\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PUT requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPATCH\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PATCH requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenJSONP\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for JSONP requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\nangular.mock.e2e = {};\nangular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];\n\n\nangular.mock.clearDataCache = function() {\n  var key,\n      cache = angular.element.cache;\n\n  for(key in cache) {\n    if (cache.hasOwnProperty(key)) {\n      var handle = cache[key].handle;\n\n      handle && angular.element(handle.elem).unbind();\n      delete cache[key];\n    }\n  }\n};\n\n\nwindow.jstestdriver && (function(window) {\n  /**\n   * Global method to output any number of objects into JSTD console. Useful for debugging.\n   */\n  window.dump = function() {\n    var args = [];\n    angular.forEach(arguments, function(arg) {\n      args.push(angular.mock.dump(arg));\n    });\n    jstestdriver.console.log.apply(jstestdriver.console, args);\n    if (window.console) {\n      window.console.log.apply(window.console, args);\n    }\n  };\n})(window);\n\n\nwindow.jasmine && (function(window) {\n\n  afterEach(function() {\n    var spec = getCurrentSpec();\n    var injector = spec.$injector;\n\n    spec.$injector = null;\n    spec.$modules = null;\n\n    if (injector) {\n      injector.get('$rootElement').unbind();\n      injector.get('$browser').pollFns.length = 0;\n    }\n\n    angular.mock.clearDataCache();\n\n    // clean up jquery's fragment cache\n    angular.forEach(angular.element.fragments, function(val, key) {\n      delete angular.element.fragments[key];\n    });\n\n    MockXhr.$$lastInstance = null;\n\n    angular.forEach(angular.callbacks, function(val, key) {\n      delete angular.callbacks[key];\n    });\n    angular.callbacks.counter = 0;\n  });\n\n  function getCurrentSpec() {\n    return jasmine.getEnv().currentSpec;\n  }\n\n  function isSpecRunning() {\n    var spec = getCurrentSpec();\n    return spec && spec.queue.running;\n  }\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.module\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * This function registers a module configuration code. It collects the configuration information\n   * which will be used when the injector is created by {@link angular.mock.inject inject}.\n   *\n   * See {@link angular.mock.inject inject} for usage example\n   *\n   * @param {...(string|Function)} fns any number of modules which are represented as string\n   *        aliases or as anonymous module initialization functions. The modules are used to\n   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.\n   */\n  window.module = angular.mock.module = function() {\n    var moduleFns = Array.prototype.slice.call(arguments, 0);\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      if (spec.$injector) {\n        throw Error('Injector already created, can not register a module!');\n      } else {\n        var modules = spec.$modules || (spec.$modules = []);\n        angular.forEach(moduleFns, function(module) {\n          modules.push(module);\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.inject\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * The inject function wraps a function into an injectable function. The inject() creates new\n   * instance of {@link AUTO.$injector $injector} per test, which is then used for\n   * resolving references.\n   *\n   * See also {@link angular.mock.module module}\n   *\n   * Example of what a typical jasmine tests looks like with the inject method.\n   * <pre>\n   *\n   *   angular.module('myApplicationModule', [])\n   *       .value('mode', 'app')\n   *       .value('version', 'v1.0.1');\n   *\n   *\n   *   describe('MyApp', function() {\n   *\n   *     // You need to load modules that you want to test,\n   *     // it loads only the \"ng\" module by default.\n   *     beforeEach(module('myApplicationModule'));\n   *\n   *\n   *     // inject() is used to inject arguments of all given functions\n   *     it('should provide a version', inject(function(mode, version) {\n   *       expect(version).toEqual('v1.0.1');\n   *       expect(mode).toEqual('app');\n   *     }));\n   *\n   *\n   *     // The inject and module method can also be used inside of the it or beforeEach\n   *     it('should override a version and test the new version is injected', function() {\n   *       // module() takes functions or strings (module aliases)\n   *       module(function($provide) {\n   *         $provide.value('version', 'overridden'); // override version here\n   *       });\n   *\n   *       inject(function(version) {\n   *         expect(version).toEqual('overridden');\n   *       });\n   *     ));\n   *   });\n   *\n   * </pre>\n   *\n   * @param {...Function} fns any number of functions which will be injected using the injector.\n   */\n  window.inject = angular.mock.inject = function() {\n    var blockFns = Array.prototype.slice.call(arguments, 0);\n    var errorForStack = new Error('Declaration Location');\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      var modules = spec.$modules || [];\n      modules.unshift('ngMock');\n      modules.unshift('ng');\n      var injector = spec.$injector;\n      if (!injector) {\n        injector = spec.$injector = angular.injector(modules);\n      }\n      for(var i = 0, ii = blockFns.length; i < ii; i++) {\n        try {\n          injector.invoke(blockFns[i] || angular.noop, this);\n        } catch (e) {\n          if(e.stack) e.stack +=  '\\n' + errorForStack.stack;\n          throw e;\n        } finally {\n          errorForStack = null;\n        }\n      }\n    }\n  };\n})(window);\n"
  },
  {
    "path": "chapter5/recipe5/test/lib/angular/angular-scenario.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Mar 21 12:46:34 2012 -0700\n */\n(function( window, undefined ) {\n'use strict';\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.7.2\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in array && array[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n\t\tvar exec,\n\t\t\tbulk = key == null,\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\n\t\t// Sets many values\n\t\tif ( key && typeof key === \"object\" ) {\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n\t\t\t}\n\t\t\tchainable = 1;\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = pass === undefined && jQuery.isFunction( value );\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations only iterate when executing function values\n\t\t\t\tif ( exec ) {\n\t\t\t\t\texec = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn exec.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\n\t\t\t\t// Otherwise they run against the entire set\n\t\t\t\t} else {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor (; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchainable = 1;\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfired = true;\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar length = list.length;\n\t\t\t\t\tadd( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory || memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tfragment,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tpixelMargin: true\n\t};\n\n\t// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead\n\tjQuery.boxModel = support.boxModel = (document.compatMode === \"CSS1Compat\");\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor ( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\tfragment.removeChild( div );\n\n\t// Null elements to avoid leaks in IE\n\tfragment = select = opt = div = input = null;\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tmarginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,\n\t\t\tpaddingMarginBorderVisibility, paddingMarginBorder,\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tconMarginTop = 1;\n\t\tpaddingMarginBorder = \"padding:0;margin:0;border:\";\n\t\tpositionTopLeftWidthHeight = \"position:absolute;top:0;left:0;width:1px;height:1px;\";\n\t\tpaddingMarginBorderVisibility = paddingMarginBorder + \"0;visibility:hidden;\";\n\t\tstyle = \"style='\" + positionTopLeftWidthHeight + paddingMarginBorder + \"5px solid #000;\";\n\t\thtml = \"<div \" + style + \"display:block;'><div style='\" + paddingMarginBorder + \"0;display:block;overflow:hidden;'></div></div>\" +\n\t\t\t\"<table \" + style + \"' cellpadding='0' cellspacing='0'>\" +\n\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = paddingMarginBorderVisibility + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td style='\" + paddingMarginBorder + \"0;display:none'></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName( \"td\" );\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t// gets computed margin-right based on width of container. For more\n\t\t// info see bug #3333\n\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tmarginDiv = document.createElement( \"div\" );\n\t\t\tmarginDiv.style.width = \"0\";\n\t\t\tmarginDiv.style.marginRight = \"0\";\n\t\t\tdiv.style.width = \"2px\";\n\t\t\tdiv.appendChild( marginDiv );\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\t// (IE < 8 does this)\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.width = div.style.padding = \"1px\";\n\t\t\tdiv.style.border = 0;\n\t\t\tdiv.style.overflow = \"hidden\";\n\t\t\tdiv.style.display = \"inline\";\n\t\t\tdiv.style.zoom = 1;\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.style.overflow = \"visible\";\n\t\t\tdiv.innerHTML = \"<div style='width:5px;'></div>\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\t\t}\n\n\t\tdiv.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;\n\t\tdiv.innerHTML = html;\n\n\t\touter = div.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.style.marginTop = \"1%\";\n\t\t\tsupport.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== \"1%\";\n\t\t}\n\n\t\tif ( typeof container.style.zoom !== \"undefined\" ) {\n\t\t\tcontainer.style.zoom = 1;\n\t\t}\n\n\t\tbody.removeChild( container );\n\t\tmarginDiv = div = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\treturn support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ internalKey ] : internalKey;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ internalKey ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( internalKey );\n\t\t\t} else {\n\t\t\t\telem[ internalKey ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, part, attr, name, l,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = elem.attributes;\n\t\t\t\t\tfor ( l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split( \".\", 2 );\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\t\tpart = parts[1] + \"!\";\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\tdata = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\tif ( data === undefined && elem ) {\n\t\t\t\t\tdata = jQuery.data( elem, key );\n\t\t\t\t\tdata = dataAttr( elem, key, data );\n\t\t\t\t}\n\n\t\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\t\tdata;\n\t\t\t}\n\n\t\t\tparts[1] = value;\n\t\t\tthis.each(function() {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.triggerHandler( \"setData\" + part, parts );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + part, parts );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, false );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\thooks = {};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( object );\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, l, isBool,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\t\t\tattrNames = value.toLowerCase().split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tisBool = rboolean.test( name );\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\t// Do not do this for boolean attributes (see #10870)\n\t\t\t\t\tif ( !isBool ) {\n\t\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\t}\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( isBool && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true,\n\t\tcoords: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = \"\" + value );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+)?\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\tvar attrs = elem.attributes || {};\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || (attrs.id || {}).value === m[2]) &&\n\t\t\t(!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tquick: selector && quickParse( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t ( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\told = null;\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\tspecial = jQuery.event.special[ event.type ] || {},\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n\t\t\t// Pregenerate a single jQuery object for reuse with .is()\n\t\t\tjqcur = jQuery(this);\n\t\t\tjqcur.context = this.ownerDocument || this;\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process events on disabled elements (#6911, #8165)\n\t\t\t\tif ( cur.disabled !== true ) {\n\t\t\t\t\tselMatch = {};\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tjqcur[0] = cur;\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\t\tselMatch[ sel ] = (\n\t\t\t\t\t\t\t\thandleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\tret;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\t\t\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\telem._change_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) { // && selector != null\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( var type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\n\t\t\tparts.push( m[1] );\n\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\t\t/* falls through */\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n// Expose origPOS\n// \"global\" as in regardless of relation to brackets/parens\nExpr.match.globalPOS = origPOS;\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry {\n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.globalPOS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\tPOS.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery.clean(arguments) );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tnull;\n\t\t\t}\n\n\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, function( i, elem ) {\n\t\t\t\t\tif ( elem.src ) {\n\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\turl: elem.src,\n\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\tdataType: \"script\"\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\n\t// IE blanks contents when cloning scripts\n\t} else if ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdest.text = src.text;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n\n\t// Clear flags for bubbling special change/submit events, they must\n\t// be reattached when the newly cloned events are first activated\n\tdest.removeAttribute( \"_submit_attached\" );\n\tdest.removeAttribute( \"_change_attached\" );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n\t// Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n\tvar div = document.createElement( \"div\" );\n\tsafeFragment.appendChild( div );\n\n\tdiv.innerHTML = elem.outerHTML;\n\treturn div.firstChild;\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t\tclone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ?\n\t\t\t\telem.cloneNode( true ) :\n\t\t\t\tshimCloneNode( elem );\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType, script, j,\n\t\t\t\tret = [];\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\"),\n\t\t\t\t\t\tsafeChildNodes = safeFragment.childNodes,\n\t\t\t\t\t\tremove;\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\n\t\t\t\t\t// Clear elements from DocumentFragment (safeFragment or otherwise)\n\t\t\t\t\t// to avoid hoarding elements. Fixes #11356\n\t\t\t\t\tif ( div ) {\n\t\t\t\t\t\tdiv.parentNode.removeChild( div );\n\n\t\t\t\t\t\t// Guard against -1 index exceptions in FF3.6\n\t\t\t\t\t\tif ( safeChildNodes.length > 0 ) {\n\t\t\t\t\t\t\tremove = safeChildNodes[ safeChildNodes.length - 1 ];\n\n\t\t\t\t\t\t\tif ( remove && remove.parentNode ) {\n\t\t\t\t\t\t\t\tremove.parentNode.removeChild( remove );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tscript = ret[i];\n\t\t\t\tif ( scripts && jQuery.nodeName( script, \"script\" ) && (!script.type || rscriptType.test( script.type )) ) {\n\t\t\t\t\tscripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( script.nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( script.getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( script );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnum = /^[\\-+]?(?:\\d*\\.)?\\d+$/i,\n\trnumnonpx = /^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\trmargin = /^margin/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\n\t// order is important!\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\treturn jQuery.access( this, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t}, name, value, arguments.length > 1 );\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {},\n\t\t\tret, name;\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// DEPRECATED in 1.3, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle, width,\n\t\t\tstyle = elem.style;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( (defaultView = elem.ownerDocument.defaultView) &&\n\t\t\t\t(computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// WebKit uses \"computed value (percentage if specified)\" instead of \"used value\" for margins\n\t\t// which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {\n\t\t\twidth = style.width;\n\t\t\tstyle.width = ret;\n\t\t\tret = computedStyle.width;\n\t\t\tstyle.width = width;\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( rnumnonpx.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\ti = name === \"width\" ? 1 : 0,\n\t\tlen = 4;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tfor ( ; i < len; i += 2 ) {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ];\n\t}\n\n\t// Computed unit is not pixels. Stop here and return.\n\tif ( rnumnonpx.test(val) ) {\n\t\treturn val;\n\t}\n\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tfor ( ; i < len; i += 2 ) {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val + \"px\";\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\treturn jQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\treturn rnum.test( value ) ?\n\t\t\t\tvalue + \"px\" :\n\t\t\t\tvalue;\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\treturn curCSS( elem, \"margin-right\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i,\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n\t\t\t\texpanded = {};\n\n\t\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n});\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = ( typeof s.data === \"string\" ) && /^application\\/x\\-www\\-form\\-urlencoded/.test( s.contentType );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t} catch( _ ) {\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( (display === \"\" && jQuery.css(elem, \"display\") === \"none\") ||\n\t\t\t\t\t\t!jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e, hooks, replace,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\t// first pass over propertys to expand / normalize\n\t\t\tfor ( p in prop ) {\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tif ( ( hooks = jQuery.cssHooks[ name ] ) && \"expand\" in hooks ) {\n\t\t\t\t\treplace = hooks.expand( prop[ name ] );\n\t\t\t\t\tdelete prop[ name ];\n\n\t\t\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t\t\t// also - reusing 'p' from above because we have the correct \"name\"\n\t\t\t\t\tfor ( p in replace ) {\n\t\t\t\t\t\tif ( ! ( p in prop ) ) {\n\t\t\t\t\t\t\tprop[ p ] = replace[ p ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( name in prop ) {\n\t\t\t\tval = prop[ name ];\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, index ) {\n\t\t\t\tvar hooks = data[ index ];\n\t\t\t\tjQuery.removeData( elem, index, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n\t\t\t\tstopQueue( this, data, index );\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ index ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ index ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p ) {\n\t\t\treturn p;\n\t\t},\n\t\tswing: function( p ) {\n\t\t\treturn ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tif ( self.options.hide ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t\t} else if ( self.options.show ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.end );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Ensure props that can't be negative don't go there on undershoot easing\njQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {\n\t// exclude marginTop, marginLeft, marginBottom and marginRight from this list\n\tif ( prop.indexOf( \"margin\" ) ) {\n\t\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( jQuery.support.boxModel ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar getOffset,\n\trtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tgetOffset = function( elem, doc, docElem, box ) {\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow( doc ),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tgetOffset = function( elem, doc, docElem ) {\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar elem = this[0],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn null;\n\t}\n\n\tif ( elem === doc.body ) {\n\t\treturn jQuery.offset.bodyOffset( elem );\n\t}\n\n\treturn getOffset( elem, doc, doc.documentElement );\n};\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t top ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tvar clientProp = \"client\" + name,\n\t\tscrollProp = \"scroll\" + name,\n\t\toffsetProp = \"offset\" + name;\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( value ) {\n\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\tvar doc, docElemProp, orig, ret;\n\n\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\t\tdoc = elem.document;\n\t\t\t\tdocElemProp = doc.documentElement[ clientProp ];\n\t\t\t\treturn jQuery.support.boxModel && docElemProp ||\n\t\t\t\t\tdoc.body && doc.body[ clientProp ] || docElemProp;\n\t\t\t}\n\n\t\t\t// Get document width or height\n\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t// when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]\n\t\t\t\t// so we can't use max, as it'll choose the incorrect offset[Width/Height]\n\t\t\t\t// instead we use the correct client[Width/Height]\n\t\t\t\t// support:IE6\n\t\t\t\tif ( doc[ clientProp ] >= doc[ scrollProp ] ) {\n\t\t\t\t\treturn doc[ clientProp ];\n\t\t\t\t}\n\n\t\t\t\treturn Math.max(\n\t\t\t\t\telem.body[ scrollProp ], doc[ scrollProp ],\n\t\t\t\t\telem.body[ offsetProp ], doc[ offsetProp ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get width or height on the element\n\t\t\tif ( value === undefined ) {\n\t\t\t\torig = jQuery.css( elem, type );\n\t\t\t\tret = parseFloat( orig );\n\t\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\t\t\t}\n\n\t\t\t// Set the width or height on the element\n\t\t\tjQuery( elem ).css( type, value );\n\t\t}, type, value, arguments.length, null );\n\t};\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );\n/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document){\n  var _jQuery = window.jQuery.noConflict(true);\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n\n/**\n * Setup file for the Scenario.\n * Must be first in the compilation/bootstrap list.\n */\n\n// Public namespace\nangular.scenario = angular.scenario || {};\n\n/**\n * Defines a new output format.\n *\n * @param {string} name the name of the new output format\n * @param {function()} fn function(context, runner) that generates the output\n */\nangular.scenario.output = angular.scenario.output || function(name, fn) {\n  angular.scenario.output[name] = fn;\n};\n\n/**\n * Defines a new DSL statement. If your factory function returns a Future\n * it's returned, otherwise the result is assumed to be a map of functions\n * for chaining. Chained functions are subject to the same rules.\n *\n * Note: All functions on the chain are bound to the chain scope so values\n *   set on \"this\" in your statement function are available in the chained\n *   functions.\n *\n * @param {string} name The name of the statement\n * @param {function()} fn Factory function(), return a function for\n *  the statement.\n */\nangular.scenario.dsl = angular.scenario.dsl || function(name, fn) {\n  angular.scenario.dsl[name] = function() {\n    function executeStatement(statement, args) {\n      var result = statement.apply(this, args);\n      if (angular.isFunction(result) || result instanceof angular.scenario.Future)\n        return result;\n      var self = this;\n      var chain = angular.extend({}, result);\n      angular.forEach(chain, function(value, name) {\n        if (angular.isFunction(value)) {\n          chain[name] = function() {\n            return executeStatement.call(self, value, arguments);\n          };\n        } else {\n          chain[name] = value;\n        }\n      });\n      return chain;\n    }\n    var statement = fn.apply(this, arguments);\n    return function() {\n      return executeStatement.call(this, statement, arguments);\n    };\n  };\n};\n\n/**\n * Defines a new matcher for use with the expects() statement. The value\n * this.actual (like in Jasmine) is available in your matcher to compare\n * against. Your function should return a boolean. The future is automatically\n * created for you.\n *\n * @param {string} name The name of the matcher\n * @param {function()} fn The matching function(expected).\n */\nangular.scenario.matcher = angular.scenario.matcher || function(name, fn) {\n  angular.scenario.matcher[name] = function(expected) {\n    var prefix = 'expect ' + this.future.name + ' ';\n    if (this.inverse) {\n      prefix += 'not ';\n    }\n    var self = this;\n    this.addFuture(prefix + name + ' ' + angular.toJson(expected),\n      function(done) {\n        var error;\n        self.actual = self.future.value;\n        if ((self.inverse && fn.call(self, expected)) ||\n            (!self.inverse && !fn.call(self, expected))) {\n          error = 'expected ' + angular.toJson(expected) +\n            ' but was ' + angular.toJson(self.actual);\n        }\n        done(error);\n    });\n  };\n};\n\n/**\n * Initialize the scenario runner and run !\n *\n * Access global window and document object\n * Access $runner through closure\n *\n * @param {Object=} config Config options\n */\nangular.scenario.setUpAndRun = function(config) {\n  var href = window.location.href;\n  var body = _jQuery(document.body);\n  var output = [];\n  var objModel = new angular.scenario.ObjectModel($runner);\n\n  if (config && config.scenario_output) {\n    output = config.scenario_output.split(',');\n  }\n\n  angular.forEach(angular.scenario.output, function(fn, name) {\n    if (!output.length || indexOf(output,name) != -1) {\n      var context = body.append('<div></div>').find('div:last');\n      context.attr('id', name);\n      fn.call({}, context, $runner, objModel);\n    }\n  });\n\n  if (!/^http/.test(href) && !/^https/.test(href)) {\n    body.append('<p id=\"system-error\"></p>');\n    body.find('#system-error').text(\n      'Scenario runner must be run using http or https. The protocol ' +\n      href.split(':')[0] + ':// is not supported.'\n    );\n    return;\n  }\n\n  var appFrame = body.append('<div id=\"application\"></div>').find('#application');\n  var application = new angular.scenario.Application(appFrame);\n\n  $runner.on('RunnerEnd', function() {\n    appFrame.css('display', 'none');\n    appFrame.find('iframe').attr('src', 'about:blank');\n  });\n\n  $runner.on('RunnerError', function(error) {\n    if (window.console) {\n      console.log(formatException(error));\n    } else {\n      // Do something for IE\n      alert(error);\n    }\n  });\n\n  $runner.run(application);\n};\n\n/**\n * Iterates through list with iterator function that must call the\n * continueFunction to continute iterating.\n *\n * @param {Array} list list to iterate over\n * @param {function()} iterator Callback function(value, continueFunction)\n * @param {function()} done Callback function(error, result) called when\n *   iteration finishes or an error occurs.\n */\nfunction asyncForEach(list, iterator, done) {\n  var i = 0;\n  function loop(error, index) {\n    if (index && index > i) {\n      i = index;\n    }\n    if (error || i >= list.length) {\n      done(error);\n    } else {\n      try {\n        iterator(list[i++], loop);\n      } catch (e) {\n        done(e);\n      }\n    }\n  }\n  loop();\n}\n\n/**\n * Formats an exception into a string with the stack trace, but limits\n * to a specific line length.\n *\n * @param {Object} error The exception to format, can be anything throwable\n * @param {Number=} [maxStackLines=5] max lines of the stack trace to include\n *  default is 5.\n */\nfunction formatException(error, maxStackLines) {\n  maxStackLines = maxStackLines || 5;\n  var message = error.toString();\n  if (error.stack) {\n    var stack = error.stack.split('\\n');\n    if (stack[0].indexOf(message) === -1) {\n      maxStackLines++;\n      stack.unshift(error.message);\n    }\n    message = stack.slice(0, maxStackLines).join('\\n');\n  }\n  return message;\n}\n\n/**\n * Returns a function that gets the file name and line number from a\n * location in the stack if available based on the call site.\n *\n * Note: this returns another function because accessing .stack is very\n * expensive in Chrome.\n *\n * @param {Number} offset Number of stack lines to skip\n */\nfunction callerFile(offset) {\n  var error = new Error();\n\n  return function() {\n    var line = (error.stack || '').split('\\n')[offset];\n\n    // Clean up the stack trace line\n    if (line) {\n      if (line.indexOf('@') !== -1) {\n        // Firefox\n        line = line.substring(line.indexOf('@')+1);\n      } else {\n        // Chrome\n        line = line.substring(line.indexOf('(')+1).replace(')', '');\n      }\n    }\n\n    return line || '';\n  };\n}\n\n/**\n * Triggers a browser event. Attempts to choose the right event if one is\n * not specified.\n *\n * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement\n * @param {string} type Optional event type.\n * @param {Array.<string>=} keys Optional list of pressed keys\n *        (valid values: 'alt', 'meta', 'shift', 'ctrl')\n */\nfunction browserTrigger(element, type, keys) {\n  if (element && !element.nodeName) element = element[0];\n  if (!element) return;\n  if (!type) {\n    type = {\n        'text':            'change',\n        'textarea':        'change',\n        'hidden':          'change',\n        'password':        'change',\n        'button':          'click',\n        'submit':          'click',\n        'reset':           'click',\n        'image':           'click',\n        'checkbox':        'click',\n        'radio':           'click',\n        'select-one':      'change',\n        'select-multiple': 'change'\n    }[lowercase(element.type)] || 'click';\n  }\n  if (lowercase(nodeName_(element)) == 'option') {\n    element.parentNode.value = element.value;\n    element = element.parentNode;\n    type = 'change';\n  }\n\n  keys = keys || [];\n  function pressed(key) {\n    return indexOf(keys, key) !== -1;\n  }\n\n  if (msie < 9) {\n    switch(element.type) {\n      case 'radio':\n      case 'checkbox':\n        element.checked = !element.checked;\n        break;\n    }\n    // WTF!!! Error: Unspecified error.\n    // Don't know why, but some elements when detached seem to be in inconsistent state and\n    // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)\n    // forcing the browser to compute the element position (by reading its CSS)\n    // puts the element in consistent state.\n    element.style.posLeft;\n\n    // TODO(vojta): create event objects with pressed keys to get it working on IE<9\n    var ret = element.fireEvent('on' + type);\n    if (lowercase(element.type) == 'submit') {\n      while(element) {\n        if (lowercase(element.nodeName) == 'form') {\n          element.fireEvent('onsubmit');\n          break;\n        }\n        element = element.parentNode;\n      }\n    }\n    return ret;\n  } else {\n    var evnt = document.createEvent('MouseEvents'),\n        originalPreventDefault = evnt.preventDefault,\n        iframe = _jQuery('#application iframe')[0],\n        appWindow = iframe ? iframe.contentWindow : window,\n        fakeProcessDefault = true,\n        finalProcessDefault,\n        angular = appWindow.angular || {};\n\n    // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208\n    angular['ff-684208-preventDefault'] = false;\n    evnt.preventDefault = function() {\n      fakeProcessDefault = false;\n      return originalPreventDefault.apply(evnt, arguments);\n    };\n\n    evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, pressed('ctrl'), pressed('alt'),\n                        pressed('shift'), pressed('meta'), 0, element);\n\n    element.dispatchEvent(evnt);\n    finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);\n\n    delete angular['ff-684208-preventDefault'];\n\n    return finalProcessDefault;\n  }\n}\n\n/**\n * Don't use the jQuery trigger method since it works incorrectly.\n *\n * jQuery notifies listeners and then changes the state of a checkbox and\n * does not create a real browser event. A real click changes the state of\n * the checkbox and then notifies listeners.\n *\n * To work around this we instead use our own handler that fires a real event.\n */\n(function(fn){\n  var parentTrigger = fn.trigger;\n  fn.trigger = function(type) {\n    if (/(click|change|keydown|blur|input)/.test(type)) {\n      var processDefaults = [];\n      this.each(function(index, node) {\n        processDefaults.push(browserTrigger(node, type));\n      });\n\n      // this is not compatible with jQuery - we return an array of returned values,\n      // so that scenario runner know whether JS code has preventDefault() of the event or not...\n      return processDefaults;\n    }\n    return parentTrigger.apply(this, arguments);\n  };\n})(_jQuery.fn);\n\n/**\n * Finds all bindings with the substring match of name and returns an\n * array of their values.\n *\n * @param {string} bindExp The name to match\n * @return {Array.<string>} String of binding values\n */\n_jQuery.fn.bindings = function(windowJquery, bindExp) {\n  var result = [], match,\n      bindSelector = '.ng-binding:visible';\n  if (angular.isString(bindExp)) {\n    bindExp = bindExp.replace(/\\s/g, '');\n    match = function (actualExp) {\n      if (actualExp) {\n        actualExp = actualExp.replace(/\\s/g, '');\n        if (actualExp == bindExp) return true;\n        if (actualExp.indexOf(bindExp) == 0) {\n          return actualExp.charAt(bindExp.length) == '|';\n        }\n      }\n    }\n  } else if (bindExp) {\n    match = function(actualExp) {\n      return actualExp && bindExp.exec(actualExp);\n    }\n  } else {\n    match = function(actualExp) {\n      return !!actualExp;\n    };\n  }\n  var selection = this.find(bindSelector);\n  if (this.is(bindSelector)) {\n    selection = selection.add(this);\n  }\n\n  function push(value) {\n    if (value == undefined) {\n      value = '';\n    } else if (typeof value != 'string') {\n      value = angular.toJson(value);\n    }\n    result.push('' + value);\n  }\n\n  selection.each(function() {\n    var element = windowJquery(this),\n        binding;\n    if (binding = element.data('$binding')) {\n      if (typeof binding == 'string') {\n        if (match(binding)) {\n          push(element.scope().$eval(binding));\n        }\n      } else {\n        if (!angular.isArray(binding)) {\n          binding = [binding];\n        }\n        for(var fns, j=0, jj=binding.length;  j<jj; j++) {\n          fns = binding[j];\n          if (fns.parts) {\n            fns = fns.parts;\n          } else {\n            fns = [fns];\n          }\n          for (var scope, fn, i = 0, ii = fns.length; i < ii; i++) {\n            if(match((fn = fns[i]).exp)) {\n              push(fn(scope = scope || element.scope()));\n            }\n          }\n        }\n      }\n    }\n  });\n  return result;\n};\n\n/**\n * Represents the application currently being tested and abstracts usage\n * of iframes or separate windows.\n *\n * @param {Object} context jQuery wrapper around HTML context.\n */\nangular.scenario.Application = function(context) {\n  this.context = context;\n  context.append(\n    '<h2>Current URL: <a href=\"about:blank\">None</a></h2>' +\n    '<div id=\"test-frames\"></div>'\n  );\n};\n\n/**\n * Gets the jQuery collection of frames. Don't use this directly because\n * frames may go stale.\n *\n * @private\n * @return {Object} jQuery collection\n */\nangular.scenario.Application.prototype.getFrame_ = function() {\n  return this.context.find('#test-frames iframe:last');\n};\n\n/**\n * Gets the window of the test runner frame. Always favor executeAction()\n * instead of this method since it prevents you from getting a stale window.\n *\n * @private\n * @return {Object} the window of the frame\n */\nangular.scenario.Application.prototype.getWindow_ = function() {\n  var contentWindow = this.getFrame_().prop('contentWindow');\n  if (!contentWindow)\n    throw 'Frame window is not accessible.';\n  return contentWindow;\n};\n\n/**\n * Changes the location of the frame.\n *\n * @param {string} url The URL. If it begins with a # then only the\n *   hash of the page is changed.\n * @param {function()} loadFn function($window, $document) Called when frame loads.\n * @param {function()} errorFn function(error) Called if any error when loading.\n */\nangular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorFn) {\n  var self = this;\n  var frame = this.getFrame_();\n  //TODO(esprehn): Refactor to use rethrow()\n  errorFn = errorFn || function(e) { throw e; };\n  if (url === 'about:blank') {\n    errorFn('Sandbox Error: Navigating to about:blank is not allowed.');\n  } else if (url.charAt(0) === '#') {\n    url = frame.attr('src').split('#')[0] + url;\n    frame.attr('src', url);\n    this.executeAction(loadFn);\n  } else {\n    frame.remove();\n    this.context.find('#test-frames').append('<iframe>');\n    frame = this.getFrame_();\n    frame.load(function() {\n      frame.unbind();\n      try {\n        self.executeAction(loadFn);\n      } catch (e) {\n        errorFn(e);\n      }\n    }).attr('src', url);\n  }\n  this.context.find('> h2 a').attr('href', url).text(url);\n};\n\n/**\n * Executes a function in the context of the tested application. Will wait\n * for all pending angular xhr requests before executing.\n *\n * @param {function()} action The callback to execute. function($window, $document)\n *  $document is a jQuery wrapped document.\n */\nangular.scenario.Application.prototype.executeAction = function(action) {\n  var self = this;\n  var $window = this.getWindow_();\n  if (!$window.document) {\n    throw 'Sandbox Error: Application document not accessible.';\n  }\n  if (!$window.angular) {\n    return action.call(this, $window, _jQuery($window.document));\n  }\n  angularInit($window.document, function(element) {\n    var $injector = $window.angular.element(element).injector();\n    var $element = _jQuery(element);\n\n    $element.injector = function() {\n      return $injector;\n    };\n\n    $injector.invoke(function($browser){\n      $browser.notifyWhenNoOutstandingRequests(function() {\n        action.call(self, $window, $element);\n      });\n    });\n  });\n};\n\n/**\n * The representation of define blocks. Don't used directly, instead use\n * define() in your tests.\n *\n * @param {string} descName Name of the block\n * @param {Object} parent describe or undefined if the root.\n */\nangular.scenario.Describe = function(descName, parent) {\n  this.only = parent && parent.only;\n  this.beforeEachFns = [];\n  this.afterEachFns = [];\n  this.its = [];\n  this.children = [];\n  this.name = descName;\n  this.parent = parent;\n  this.id = angular.scenario.Describe.id++;\n\n  /**\n   * Calls all before functions.\n   */\n  var beforeEachFns = this.beforeEachFns;\n  this.setupBefore = function() {\n    if (parent) parent.setupBefore.call(this);\n    angular.forEach(beforeEachFns, function(fn) { fn.call(this); }, this);\n  };\n\n  /**\n   * Calls all after functions.\n   */\n  var afterEachFns = this.afterEachFns;\n  this.setupAfter  = function() {\n    angular.forEach(afterEachFns, function(fn) { fn.call(this); }, this);\n    if (parent) parent.setupAfter.call(this);\n  };\n};\n\n// Shared Unique ID generator for every describe block\nangular.scenario.Describe.id = 0;\n\n// Shared Unique ID generator for every it (spec)\nangular.scenario.Describe.specId = 0;\n\n/**\n * Defines a block to execute before each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.beforeEach = function(body) {\n  this.beforeEachFns.push(body);\n};\n\n/**\n * Defines a block to execute after each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.afterEach = function(body) {\n  this.afterEachFns.push(body);\n};\n\n/**\n * Creates a new describe block that's a child of this one.\n *\n * @param {string} name Name of the block. Appended to the parent block's name.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.describe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Same as describe() but makes ddescribe blocks the only to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.ddescribe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  child.only = true;\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Use to disable a describe block.\n */\nangular.scenario.Describe.prototype.xdescribe = angular.noop;\n\n/**\n * Defines a test.\n *\n * @param {string} name Name of the test.\n * @param {function()} vody Body of the block.\n */\nangular.scenario.Describe.prototype.it = function(name, body) {\n  this.its.push({\n    id: angular.scenario.Describe.specId++,\n    definition: this,\n    only: this.only,\n    name: name,\n    before: this.setupBefore,\n    body: body,\n    after: this.setupAfter\n  });\n};\n\n/**\n * Same as it() but makes iit tests the only test to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.iit = function(name, body) {\n  this.it.apply(this, arguments);\n  this.its[this.its.length-1].only = true;\n};\n\n/**\n * Use to disable a test block.\n */\nangular.scenario.Describe.prototype.xit = angular.noop;\n\n/**\n * Gets an array of functions representing all the tests (recursively).\n * that can be executed with SpecRunner's.\n *\n * @return {Array<Object>} Array of it blocks {\n *   definition : Object // parent Describe\n *   only: boolean\n *   name: string\n *   before: Function\n *   body: Function\n *   after: Function\n *  }\n */\nangular.scenario.Describe.prototype.getSpecs = function() {\n  var specs = arguments[0] || [];\n  angular.forEach(this.children, function(child) {\n    child.getSpecs(specs);\n  });\n  angular.forEach(this.its, function(it) {\n    specs.push(it);\n  });\n  var only = [];\n  angular.forEach(specs, function(it) {\n    if (it.only) {\n      only.push(it);\n    }\n  });\n  return (only.length && only) || specs;\n};\n\n/**\n * A future action in a spec.\n *\n * @param {string} name of the future action\n * @param {function()} future callback(error, result)\n * @param {function()} Optional. function that returns the file/line number.\n */\nangular.scenario.Future = function(name, behavior, line) {\n  this.name = name;\n  this.behavior = behavior;\n  this.fulfilled = false;\n  this.value = undefined;\n  this.parser = angular.identity;\n  this.line = line || function() { return ''; };\n};\n\n/**\n * Executes the behavior of the closure.\n *\n * @param {function()} doneFn Callback function(error, result)\n */\nangular.scenario.Future.prototype.execute = function(doneFn) {\n  var self = this;\n  this.behavior(function(error, result) {\n    self.fulfilled = true;\n    if (result) {\n      try {\n        result = self.parser(result);\n      } catch(e) {\n        error = e;\n      }\n    }\n    self.value = error || result;\n    doneFn(error, result);\n  });\n};\n\n/**\n * Configures the future to convert it's final with a function fn(value)\n *\n * @param {function()} fn function(value) that returns the parsed value\n */\nangular.scenario.Future.prototype.parsedWith = function(fn) {\n  this.parser = fn;\n  return this;\n};\n\n/**\n * Configures the future to parse it's final value from JSON\n * into objects.\n */\nangular.scenario.Future.prototype.fromJson = function() {\n  return this.parsedWith(angular.fromJson);\n};\n\n/**\n * Configures the future to convert it's final value from objects\n * into JSON.\n */\nangular.scenario.Future.prototype.toJson = function() {\n  return this.parsedWith(angular.toJson);\n};\n\n/**\n * Maintains an object tree from the runner events.\n *\n * @param {Object} runner The scenario Runner instance to connect to.\n *\n * TODO(esprehn): Every output type creates one of these, but we probably\n *  want one global shared instance. Need to handle events better too\n *  so the HTML output doesn't need to do spec model.getSpec(spec.id)\n *  silliness.\n *\n * TODO(vojta) refactor on, emit methods (from all objects) - use inheritance\n */\nangular.scenario.ObjectModel = function(runner) {\n  var self = this;\n\n  this.specMap = {};\n  this.listeners = [];\n  this.value = {\n    name: '',\n    children: {}\n  };\n\n  runner.on('SpecBegin', function(spec) {\n    var block = self.value,\n        definitions = [];\n\n    angular.forEach(self.getDefinitionPath(spec), function(def) {\n      if (!block.children[def.name]) {\n        block.children[def.name] = {\n          id: def.id,\n          name: def.name,\n          children: {},\n          specs: {}\n        };\n      }\n      block = block.children[def.name];\n      definitions.push(def.name);\n    });\n\n    var it = self.specMap[spec.id] =\n             block.specs[spec.name] =\n             new angular.scenario.ObjectModel.Spec(spec.id, spec.name, definitions);\n\n    // forward the event\n    self.emit('SpecBegin', it);\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var it = self.getSpec(spec.id);\n    it.status = 'error';\n    it.error = error;\n\n    // forward the event\n    self.emit('SpecError', it, error);\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    complete(it);\n\n    // forward the event\n    self.emit('SpecEnd', it);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var it = self.getSpec(spec.id);\n    var step = new angular.scenario.ObjectModel.Step(step.name);\n    it.steps.push(step);\n\n    // forward the event\n    self.emit('StepBegin', it, step);\n  });\n\n  runner.on('StepEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    var step = it.getLastStep();\n    if (step.name !== step.name)\n      throw 'Events fired in the wrong order. Step names don\\'t match.';\n    complete(step);\n\n    // forward the event\n    self.emit('StepEnd', it, step);\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('failure', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepFailure', it, modelStep, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('error', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepError', it, modelStep, error);\n  });\n\n  runner.on('RunnerBegin', function() {\n    self.emit('RunnerBegin');\n  });\n  runner.on('RunnerEnd', function() {\n    self.emit('RunnerEnd');\n  });\n\n  function complete(item) {\n    item.endTime = new Date().getTime();\n    item.duration = item.endTime - item.startTime;\n    item.status = item.status || 'success';\n  }\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName Name of the event to add a handler for\n * @param {function()} listener Function that will be called when event is fired\n */\nangular.scenario.ObjectModel.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.ObjectModel.prototype.emit = function(eventName) {\n  var self = this,\n      args = Array.prototype.slice.call(arguments, 1),\n      eventName = eventName.toLowerCase();\n\n  if (this.listeners[eventName]) {\n    angular.forEach(this.listeners[eventName], function(listener) {\n      listener.apply(self, args);\n    });\n  }\n};\n\n/**\n * Computes the path of definition describe blocks that wrap around\n * this spec.\n *\n * @param spec Spec to compute the path for.\n * @return {Array<Describe>} The describe block path\n */\nangular.scenario.ObjectModel.prototype.getDefinitionPath = function(spec) {\n  var path = [];\n  var currentDefinition = spec.definition;\n  while (currentDefinition && currentDefinition.name) {\n    path.unshift(currentDefinition);\n    currentDefinition = currentDefinition.parent;\n  }\n  return path;\n};\n\n/**\n * Gets a spec by id.\n *\n * @param {string} The id of the spec to get the object for.\n * @return {Object} the Spec instance\n */\nangular.scenario.ObjectModel.prototype.getSpec = function(id) {\n  return this.specMap[id];\n};\n\n/**\n * A single it block.\n *\n * @param {string} id Id of the spec\n * @param {string} name Name of the spec\n * @param {Array<string>=} definitionNames List of all describe block names that wrap this spec\n */\nangular.scenario.ObjectModel.Spec = function(id, name, definitionNames) {\n  this.id = id;\n  this.name = name;\n  this.startTime = new Date().getTime();\n  this.steps = [];\n  this.fullDefinitionName = (definitionNames || []).join(' ');\n};\n\n/**\n * Adds a new step to the Spec.\n *\n * @param {string} step Name of the step (really name of the future)\n * @return {Object} the added step\n */\nangular.scenario.ObjectModel.Spec.prototype.addStep = function(name) {\n  var step = new angular.scenario.ObjectModel.Step(name);\n  this.steps.push(step);\n  return step;\n};\n\n/**\n * Gets the most recent step.\n *\n * @return {Object} the step\n */\nangular.scenario.ObjectModel.Spec.prototype.getLastStep = function() {\n  return this.steps[this.steps.length-1];\n};\n\n/**\n * Set status of the Spec from given Step\n *\n * @param {angular.scenario.ObjectModel.Step} step\n */\nangular.scenario.ObjectModel.Spec.prototype.setStatusFromStep = function(step) {\n  if (!this.status || step.status == 'error') {\n    this.status = step.status;\n    this.error = step.error;\n    this.line = step.line;\n  }\n};\n\n/**\n * A single step inside a Spec.\n *\n * @param {string} step Name of the step\n */\nangular.scenario.ObjectModel.Step = function(name) {\n  this.name = name;\n  this.startTime = new Date().getTime();\n};\n\n/**\n * Helper method for setting all error status related properties\n *\n * @param {string} status\n * @param {string} error\n * @param {string} line\n */\nangular.scenario.ObjectModel.Step.prototype.setErrorStatus = function(status, error, line) {\n  this.status = status;\n  this.error = error;\n  this.line = line;\n};\n\n/**\n * Runner for scenarios\n *\n * Has to be initialized before any test is loaded,\n * because it publishes the API into window (global space).\n */\nangular.scenario.Runner = function($window) {\n  this.listeners = [];\n  this.$window = $window;\n  this.rootDescribe = new angular.scenario.Describe();\n  this.currentDescribe = this.rootDescribe;\n  this.api = {\n    it: this.it,\n    iit: this.iit,\n    xit: angular.noop,\n    describe: this.describe,\n    ddescribe: this.ddescribe,\n    xdescribe: angular.noop,\n    beforeEach: this.beforeEach,\n    afterEach: this.afterEach\n  };\n  angular.forEach(this.api, angular.bind(this, function(fn, key) {\n    this.$window[key] = angular.bind(this, fn);\n  }));\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.Runner.prototype.emit = function(eventName) {\n  var self = this;\n  var args = Array.prototype.slice.call(arguments, 1);\n  eventName = eventName.toLowerCase();\n  if (!this.listeners[eventName])\n    return;\n  angular.forEach(this.listeners[eventName], function(listener) {\n    listener.apply(self, args);\n  });\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName The name of the event to add a handler for\n * @param {string} listener The fn(...) that takes the extra arguments from emit()\n */\nangular.scenario.Runner.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Defines a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.describe = function(name, body) {\n  var self = this;\n  this.currentDescribe.describe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Same as describe, but makes ddescribe the only blocks to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.ddescribe = function(name, body) {\n  var self = this;\n  this.currentDescribe.ddescribe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Defines a test in a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.it = function(name, body) {\n  this.currentDescribe.it(name, body);\n};\n\n/**\n * Same as it, but makes iit tests the only tests to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.iit = function(name, body) {\n  this.currentDescribe.iit(name, body);\n};\n\n/**\n * Defines a function to be called before each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.beforeEach = function(body) {\n  this.currentDescribe.beforeEach(body);\n};\n\n/**\n * Defines a function to be called after each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.afterEach = function(body) {\n  this.currentDescribe.afterEach(body);\n};\n\n/**\n * Creates a new spec runner.\n *\n * @private\n * @param {Object} scope parent scope\n */\nangular.scenario.Runner.prototype.createSpecRunner_ = function(scope) {\n  var child = scope.$new();\n  var Cls = angular.scenario.SpecRunner;\n\n  // Export all the methods to child scope manually as now we don't mess controllers with scopes\n  // TODO(vojta): refactor scenario runner so that these objects are not tightly coupled as current\n  for (var name in Cls.prototype)\n    child[name] = angular.bind(child, Cls.prototype[name]);\n\n  Cls.call(child);\n  return child;\n};\n\n/**\n * Runs all the loaded tests with the specified runner class on the\n * provided application.\n *\n * @param {angular.scenario.Application} application App to remote control.\n */\nangular.scenario.Runner.prototype.run = function(application) {\n  var self = this;\n  var $root = angular.injector(['ng']).get('$rootScope');\n  angular.extend($root, this);\n  angular.forEach(angular.scenario.Runner.prototype, function(fn, name) {\n    $root[name] = angular.bind(self, fn);\n  });\n  $root.application = application;\n  $root.emit('RunnerBegin');\n  asyncForEach(this.rootDescribe.getSpecs(), function(spec, specDone) {\n    var dslCache = {};\n    var runner = self.createSpecRunner_($root);\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      dslCache[key] = fn.call($root);\n    });\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      self.$window[key] = function() {\n        var line = callerFile(3);\n        var scope = runner.$new();\n\n        // Make the dsl accessible on the current chain\n        scope.dsl = {};\n        angular.forEach(dslCache, function(fn, key) {\n          scope.dsl[key] = function() {\n            return dslCache[key].apply(scope, arguments);\n          };\n        });\n\n        // Make these methods work on the current chain\n        scope.addFuture = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFuture.apply(scope, arguments);\n        };\n        scope.addFutureAction = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFutureAction.apply(scope, arguments);\n        };\n\n        return scope.dsl[key].apply(scope, arguments);\n      };\n    });\n    runner.run(spec, function() {\n      runner.$destroy();\n      specDone.apply(this, arguments);\n    });\n  },\n  function(error) {\n    if (error) {\n      self.emit('RunnerError', error);\n    }\n    self.emit('RunnerEnd');\n  });\n};\n\n/**\n * This class is the \"this\" of the it/beforeEach/afterEach method.\n * Responsibilities:\n *   - \"this\" for it/beforeEach/afterEach\n *   - keep state for single it/beforeEach/afterEach execution\n *   - keep track of all of the futures to execute\n *   - run single spec (execute each future)\n */\nangular.scenario.SpecRunner = function() {\n  this.futures = [];\n  this.afterIndex = 0;\n};\n\n/**\n * Executes a spec which is an it block with associated before/after functions\n * based on the describe nesting.\n *\n * @param {Object} spec A spec object\n * @param {function()} specDone function that is called when the spec finshes. Function(error, index)\n */\nangular.scenario.SpecRunner.prototype.run = function(spec, specDone) {\n  var self = this;\n  this.spec = spec;\n\n  this.emit('SpecBegin', spec);\n\n  try {\n    spec.before.call(this);\n    spec.body.call(this);\n    this.afterIndex = this.futures.length;\n    spec.after.call(this);\n  } catch (e) {\n    this.emit('SpecError', spec, e);\n    this.emit('SpecEnd', spec);\n    specDone();\n    return;\n  }\n\n  var handleError = function(error, done) {\n    if (self.error) {\n      return done();\n    }\n    self.error = true;\n    done(null, self.afterIndex);\n  };\n\n  asyncForEach(\n    this.futures,\n    function(future, futureDone) {\n      self.step = future;\n      self.emit('StepBegin', spec, future);\n      try {\n        future.execute(function(error) {\n          if (error) {\n            self.emit('StepFailure', spec, future, error);\n            self.emit('StepEnd', spec, future);\n            return handleError(error, futureDone);\n          }\n          self.emit('StepEnd', spec, future);\n          self.$window.setTimeout(function() { futureDone(); }, 0);\n        });\n      } catch (e) {\n        self.emit('StepError', spec, future, e);\n        self.emit('StepEnd', spec, future);\n        handleError(e, futureDone);\n      }\n    },\n    function(e) {\n      if (e) {\n        self.emit('SpecError', spec, e);\n      }\n      self.emit('SpecEnd', spec);\n      // Call done in a timeout so exceptions don't recursively\n      // call this function\n      self.$window.setTimeout(function() { specDone(); }, 0);\n    }\n  );\n};\n\n/**\n * Adds a new future action.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFuture = function(name, behavior, line) {\n  var future = new angular.scenario.Future(name, angular.bind(this, behavior), line);\n  this.futures.push(future);\n  return future;\n};\n\n/**\n * Adds a new future action to be executed on the application window.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior, line) {\n  var self = this;\n  var NG = /\\[ng\\\\\\:/;\n  return this.addFuture(name, function(done) {\n    this.application.executeAction(function($window, $document) {\n\n      //TODO(esprehn): Refactor this so it doesn't need to be in here.\n      $document.elements = function(selector) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        selector = (self.selector || '') + ' ' + (selector || '');\n        selector = _jQuery.trim(selector) || '*';\n        angular.forEach(args, function(value, index) {\n          selector = selector.replace('$' + (index + 1), value);\n        });\n        var result = $document.find(selector);\n        if (selector.match(NG)) {\n          angular.forEach(['[ng-','[data-ng-','[x-ng-'], function(value, index){\n            result = result.add(selector.replace(NG, value), $document);\n          });\n        }\n        if (!result.length) {\n          throw {\n            type: 'selector',\n            message: 'Selector ' + selector + ' did not match any elements.'\n          };\n        }\n\n        return result;\n      };\n\n      try {\n        behavior.call(self, $window, $document, done);\n      } catch(e) {\n        if (e.type && e.type === 'selector') {\n          done(e.message);\n        } else {\n          throw e;\n        }\n      }\n    });\n  }, line);\n};\n\n/**\n * Shared DSL statements that are useful to all scenarios.\n */\n\n /**\n * Usage:\n *    pause() pauses until you call resume() in the console\n */\nangular.scenario.dsl('pause', function() {\n  return function() {\n    return this.addFuture('pausing for you to resume', function(done) {\n      this.emit('InteractivePause', this.spec, this.step);\n      this.$window.resume = function() { done(); };\n    });\n  };\n});\n\n/**\n * Usage:\n *    sleep(seconds) pauses the test for specified number of seconds\n */\nangular.scenario.dsl('sleep', function() {\n  return function(time) {\n    return this.addFuture('sleep for ' + time + ' seconds', function(done) {\n      this.$window.setTimeout(function() { done(null, time * 1000); }, time * 1000);\n    });\n  };\n});\n\n/**\n * Usage:\n *    browser().navigateTo(url) Loads the url into the frame\n *    browser().navigateTo(url, fn) where fn(url) is called and returns the URL to navigate to\n *    browser().reload() refresh the page (reload the same URL)\n *    browser().window.href() window.location.href\n *    browser().window.path() window.location.pathname\n *    browser().window.search() window.location.search\n *    browser().window.hash() window.location.hash without # prefix\n *    browser().location().url() see ng.$location#url\n *    browser().location().path() see ng.$location#path\n *    browser().location().search() see ng.$location#search\n *    browser().location().hash() see ng.$location#hash\n */\nangular.scenario.dsl('browser', function() {\n  var chain = {};\n\n  chain.navigateTo = function(url, delegate) {\n    var application = this.application;\n    return this.addFuture(\"browser navigate to '\" + url + \"'\", function(done) {\n      if (delegate) {\n        url = delegate.call(this, url);\n      }\n      application.navigateTo(url, function() {\n        done(null, url);\n      }, done);\n    });\n  };\n\n  chain.reload = function() {\n    var application = this.application;\n    return this.addFutureAction('browser reload', function($window, $document, done) {\n      var href = $window.location.href;\n      application.navigateTo(href, function() {\n        done(null, href);\n      }, done);\n    });\n  };\n\n  chain.window = function() {\n    var api = {};\n\n    api.href = function() {\n      return this.addFutureAction('window.location.href', function($window, $document, done) {\n        done(null, $window.location.href);\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('window.location.path', function($window, $document, done) {\n        done(null, $window.location.pathname);\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('window.location.search', function($window, $document, done) {\n        done(null, $window.location.search);\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('window.location.hash', function($window, $document, done) {\n        done(null, $window.location.hash.replace('#', ''));\n      });\n    };\n\n    return api;\n  };\n\n  chain.location = function() {\n    var api = {};\n\n    api.url = function() {\n      return this.addFutureAction('$location.url()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').url());\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('$location.path()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').path());\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('$location.search()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').search());\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('$location.hash()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').hash());\n      });\n    };\n\n    return api;\n  };\n\n  return function() {\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    expect(future).{matcher} where matcher is one of the matchers defined\n *    with angular.scenario.matcher\n *\n * ex. expect(binding(\"name\")).toEqual(\"Elliott\")\n */\nangular.scenario.dsl('expect', function() {\n  var chain = angular.extend({}, angular.scenario.matcher);\n\n  chain.not = function() {\n    this.inverse = true;\n    return chain;\n  };\n\n  return function(future) {\n    this.future = future;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    using(selector, label) scopes the next DSL element selection\n *\n * ex.\n *   using('#foo', \"'Foo' text field\").input('bar')\n */\nangular.scenario.dsl('using', function() {\n  return function(selector, label) {\n    this.selector = _jQuery.trim((this.selector||'') + ' ' + selector);\n    if (angular.isString(label) && label.length) {\n      this.label = label + ' ( ' + this.selector + ' )';\n    } else {\n      this.label = this.selector;\n    }\n    return this.dsl;\n  };\n});\n\n/**\n * Usage:\n *    binding(name) returns the value of the first matching binding\n */\nangular.scenario.dsl('binding', function() {\n  return function(name) {\n    return this.addFutureAction(\"select binding '\" + name + \"'\", function($window, $document, done) {\n      var values = $document.elements().bindings($window.angular.element, name);\n      if (!values.length) {\n        return done(\"Binding selector '\" + name + \"' did not match.\");\n      }\n      done(null, values[0]);\n    });\n  };\n});\n\n/**\n * Usage:\n *    input(name).enter(value) enters value in input with specified name\n *    input(name).check() checks checkbox\n *    input(name).select(value) selects the radio button with specified name/value\n *    input(name).val() returns the value of the input.\n */\nangular.scenario.dsl('input', function() {\n  var chain = {};\n  var supportInputEvent =  'oninput' in document.createElement('div') && msie != 9;\n\n  chain.enter = function(value, event) {\n    return this.addFutureAction(\"input '\" + this.name + \"' enter '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      input.val(value);\n      input.trigger(event || (supportInputEvent ? 'input' : 'change'));\n      done();\n    });\n  };\n\n  chain.check = function() {\n    return this.addFutureAction(\"checkbox '\" + this.name + \"' toggle\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':checkbox');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.select = function(value) {\n    return this.addFutureAction(\"radio button '\" + this.name + \"' toggle '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.\n        elements('[ng\\\\:model=\"$1\"][value=\"$2\"]', this.name, value).filter(':radio');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.val = function() {\n    return this.addFutureAction(\"return input val\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      done(null,input.val());\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n\n/**\n * Usage:\n *    repeater('#products table', 'Product List').count() number of rows\n *    repeater('#products table', 'Product List').row(1) all bindings in row as an array\n *    repeater('#products table', 'Product List').column('product.name') all values across all rows in an array\n */\nangular.scenario.dsl('repeater', function() {\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.column = function(binding) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' column '\" + binding + \"'\", function($window, $document, done) {\n      done(null, $document.elements().bindings($window.angular.element, binding));\n    });\n  };\n\n  chain.row = function(index) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' row '\" + index + \"'\", function($window, $document, done) {\n      var matches = $document.elements().slice(index, index + 1);\n      if (!matches.length)\n        return done('row ' + index + ' out of bounds');\n      done(null, matches.bindings($window.angular.element));\n    });\n  };\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    select(name).option('value') select one option\n *    select(name).options('value1', 'value2', ...) select options from a multi select\n */\nangular.scenario.dsl('select', function() {\n  var chain = {};\n\n  chain.option = function(value) {\n    return this.addFutureAction(\"select '\" + this.name + \"' option '\" + value + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[ng\\\\:model=\"$1\"]', this.name);\n      var option = select.find('option[value=\"' + value + '\"]');\n      if (option.length) {\n        select.val(value);\n      } else {\n        option = select.find('option:contains(\"' + value + '\")');\n        if (option.length) {\n          select.val(option.val());\n        }\n      }\n      select.trigger('change');\n      done();\n    });\n  };\n\n  chain.options = function() {\n    var values = arguments;\n    return this.addFutureAction(\"select '\" + this.name + \"' options '\" + values + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[multiple][ng\\\\:model=\"$1\"]', this.name);\n      select.val(values);\n      select.trigger('change');\n      done();\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    element(selector, label).count() get the number of elements that match selector\n *    element(selector, label).click() clicks an element\n *    element(selector, label).query(fn) executes fn(selectedElements, done)\n *    element(selector, label).{method}() gets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(value) sets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(key) gets the value (as defined by jQuery, ex. attr)\n *    element(selector, label).{method}(key, value) sets the value (as defined by jQuery, ex. attr)\n */\nangular.scenario.dsl('element', function() {\n  var KEY_VALUE_METHODS = ['attr', 'css', 'prop'];\n  var VALUE_METHODS = [\n    'val', 'text', 'html', 'height', 'innerHeight', 'outerHeight', 'width',\n    'innerWidth', 'outerWidth', 'position', 'scrollLeft', 'scrollTop', 'offset'\n  ];\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.click = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' click\", function($window, $document, done) {\n      var elements = $document.elements();\n      var href = elements.attr('href');\n      var eventProcessDefault = elements.trigger('click')[0];\n\n      if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {\n        this.application.navigateTo(href, function() {\n          done();\n        }, done);\n      } else {\n        done();\n      }\n    });\n  };\n\n  chain.query = function(fn) {\n    return this.addFutureAction('element ' + this.label + ' custom query', function($window, $document, done) {\n      fn.call(this, $document.elements(), done);\n    });\n  };\n\n  angular.forEach(KEY_VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(name, value) {\n      var args = arguments,\n          futureName = (args.length == 1)\n              ? \"element '\" + this.label + \"' get \" + methodName + \" '\" + name + \"'\"\n              : \"element '\" + this.label + \"' set \" + methodName + \" '\" + name + \"' to \" + \"'\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  angular.forEach(VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(value) {\n      var args = arguments,\n          futureName = (args.length == 0)\n              ? \"element '\" + this.label + \"' \" + methodName\n              : futureName = \"element '\" + this.label + \"' set \" + methodName + \" to '\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Matchers for implementing specs. Follows the Jasmine spec conventions.\n */\n\nangular.scenario.matcher('toEqual', function(expected) {\n  return angular.equals(this.actual, expected);\n});\n\nangular.scenario.matcher('toBe', function(expected) {\n  return this.actual === expected;\n});\n\nangular.scenario.matcher('toBeDefined', function() {\n  return angular.isDefined(this.actual);\n});\n\nangular.scenario.matcher('toBeTruthy', function() {\n  return this.actual;\n});\n\nangular.scenario.matcher('toBeFalsy', function() {\n  return !this.actual;\n});\n\nangular.scenario.matcher('toMatch', function(expected) {\n  return new RegExp(expected).test(this.actual);\n});\n\nangular.scenario.matcher('toBeNull', function() {\n  return this.actual === null;\n});\n\nangular.scenario.matcher('toContain', function(expected) {\n  return includes(this.actual, expected);\n});\n\nangular.scenario.matcher('toBeLessThan', function(expected) {\n  return this.actual < expected;\n});\n\nangular.scenario.matcher('toBeGreaterThan', function(expected) {\n  return this.actual > expected;\n});\n\n/**\n * User Interface for the Scenario Runner.\n *\n * TODO(esprehn): This should be refactored now that ObjectModel exists\n *  to use angular bindings for the UI.\n */\nangular.scenario.output('html', function(context, runner, model) {\n  var specUiMap = {},\n      lastStepUiMap = {};\n\n  context.append(\n    '<div id=\"header\">' +\n    '  <h1><span class=\"angular\">AngularJS</span>: Scenario Test Runner</h1>' +\n    '  <ul id=\"status-legend\" class=\"status-display\">' +\n    '    <li class=\"status-error\">0 Errors</li>' +\n    '    <li class=\"status-failure\">0 Failures</li>' +\n    '    <li class=\"status-success\">0 Passed</li>' +\n    '  </ul>' +\n    '</div>' +\n    '<div id=\"specs\">' +\n    '  <div class=\"test-children\"></div>' +\n    '</div>'\n  );\n\n  runner.on('InteractivePause', function(spec) {\n    var ui = lastStepUiMap[spec.id];\n    ui.find('.test-title').\n      html('paused... <a href=\"javascript:resume()\">resume</a> when ready.');\n  });\n\n  runner.on('SpecBegin', function(spec) {\n    var ui = findContext(spec);\n    ui.find('> .tests').append(\n      '<li class=\"status-pending test-it\"></li>'\n    );\n    ui = ui.find('> .tests li:last');\n    ui.append(\n      '<div class=\"test-info\">' +\n      '  <p class=\"test-title\">' +\n      '    <span class=\"timer-result\"></span>' +\n      '    <span class=\"test-name\"></span>' +\n      '  </p>' +\n      '</div>' +\n      '<div class=\"scrollpane\">' +\n      '  <ol class=\"test-actions\"></ol>' +\n      '</div>'\n    );\n    ui.find('> .test-info .test-name').text(spec.name);\n    ui.find('> .test-info').click(function() {\n      var scrollpane = ui.find('> .scrollpane');\n      var actions = scrollpane.find('> .test-actions');\n      var name = context.find('> .test-info .test-name');\n      if (actions.find(':visible').length) {\n        actions.hide();\n        name.removeClass('open').addClass('closed');\n      } else {\n        actions.show();\n        scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n        name.removeClass('closed').addClass('open');\n      }\n    });\n\n    specUiMap[spec.id] = ui;\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var ui = specUiMap[spec.id];\n    ui.append('<pre></pre>');\n    ui.find('> pre').text(formatException(error));\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    ui.removeClass('status-pending');\n    ui.addClass('status-' + spec.status);\n    ui.find(\"> .test-info .timer-result\").text(spec.duration + \"ms\");\n    if (spec.status === 'success') {\n      ui.find('> .test-info .test-name').addClass('closed');\n      ui.find('> .scrollpane .test-actions').hide();\n    }\n    updateTotals(spec.status);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    ui.find('> .scrollpane .test-actions').append('<li class=\"status-pending\"></li>');\n    var stepUi = lastStepUiMap[spec.id] = ui.find('> .scrollpane .test-actions li:last');\n    stepUi.append(\n      '<div class=\"timer-result\"></div>' +\n      '<div class=\"test-title\"></div>'\n    );\n    stepUi.find('> .test-title').text(step.name);\n    var scrollpane = stepUi.parents('.scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepEnd', function(spec, step) {\n    var stepUi = lastStepUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    stepUi.find('.timer-result').text(step.duration + 'ms');\n    stepUi.removeClass('status-pending');\n    stepUi.addClass('status-' + step.status);\n    var scrollpane = specUiMap[spec.id].find('> .scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  /**\n   * Finds the context of a spec block defined by the passed definition.\n   *\n   * @param {Object} The definition created by the Describe object.\n   */\n  function findContext(spec) {\n    var currentContext = context.find('#specs');\n    angular.forEach(model.getDefinitionPath(spec), function(defn) {\n      var id = 'describe-' + defn.id;\n      if (!context.find('#' + id).length) {\n        currentContext.find('> .test-children').append(\n          '<div class=\"test-describe\" id=\"' + id + '\">' +\n          '  <h2></h2>' +\n          '  <div class=\"test-children\"></div>' +\n          '  <ul class=\"tests\"></ul>' +\n          '</div>'\n        );\n        context.find('#' + id).find('> h2').text('describe: ' + defn.name);\n      }\n      currentContext = context.find('#' + id);\n    });\n    return context.find('#describe-' + spec.definition.id);\n  }\n\n  /**\n   * Updates the test counter for the status.\n   *\n   * @param {string} the status.\n   */\n  function updateTotals(status) {\n    var legend = context.find('#status-legend .status-' + status);\n    var parts = legend.text().split(' ');\n    var value = (parts[0] * 1) + 1;\n    legend.text(value + ' ' + parts[1]);\n  }\n\n  /**\n   * Add an error to a step.\n   *\n   * @param {Object} The JQuery wrapped context\n   * @param {function()} fn() that should return the file/line number of the error\n   * @param {Object} the error.\n   */\n  function addError(context, line, error) {\n    context.find('.test-title').append('<pre></pre>');\n    var message = _jQuery.trim(line() + '\\n\\n' + formatException(error));\n    context.find('.test-title pre:last').text(message);\n  }\n});\n\n/**\n * Generates JSON output into a context.\n */\nangular.scenario.output('json', function(context, runner, model) {\n  model.on('RunnerEnd', function() {\n    context.text(angular.toJson(model.value));\n  });\n});\n\n/**\n * Generates XML output into a context.\n */\nangular.scenario.output('xml', function(context, runner, model) {\n  var $ = function(args) {return new context.init(args);};\n  model.on('RunnerEnd', function() {\n    var scenario = $('<scenario></scenario>');\n    context.append(scenario);\n    serializeXml(scenario, model.value);\n  });\n\n  /**\n   * Convert the tree into XML.\n   *\n   * @param {Object} context jQuery context to add the XML to.\n   * @param {Object} tree node to serialize\n   */\n  function serializeXml(context, tree) {\n     angular.forEach(tree.children, function(child) {\n       var describeContext = $('<describe></describe>');\n       describeContext.attr('id', child.id);\n       describeContext.attr('name', child.name);\n       context.append(describeContext);\n       serializeXml(describeContext, child);\n     });\n     var its = $('<its></its>');\n     context.append(its);\n     angular.forEach(tree.specs, function(spec) {\n       var it = $('<it></it>');\n       it.attr('id', spec.id);\n       it.attr('name', spec.name);\n       it.attr('duration', spec.duration);\n       it.attr('status', spec.status);\n       its.append(it);\n       angular.forEach(spec.steps, function(step) {\n         var stepContext = $('<step></step>');\n         stepContext.attr('name', step.name);\n         stepContext.attr('duration', step.duration);\n         stepContext.attr('status', step.status);\n         it.append(stepContext);\n         if (step.error) {\n           var error = $('<error></error>');\n           stepContext.append(error);\n           error.text(formatException(stepContext.error));\n         }\n       });\n     });\n   }\n});\n\n/**\n * Creates a global value $result with the result of the runner.\n */\nangular.scenario.output('object', function(context, runner, model) {\n  runner.$window.$result = model.value;\n});\nbindJQuery();\npublishExternalAPI(angular);\n\nvar $runner = new angular.scenario.Runner(window),\n    scripts = document.getElementsByTagName('script'),\n    script = scripts[scripts.length - 1],\n    config = {};\n\nangular.forEach(script.attributes, function(attr) {\n  var match = attr.name.match(/ng[:\\-](.*)/);\n  if (match) {\n    config[match[1]] = attr.value || true;\n  }\n});\n\nif (config.autotest) {\n  JQLite(document).ready(function() {\n    angular.scenario.setUpAndRun(config);\n  });\n}\n})(window, document);\n\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n\\n[ng\\\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\\n.ng-cloak, .x-ng-cloak {\\n  display: none;\\n}\\n\\nng\\\\:form {\\n  display: block;\\n}\\n</style>');\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n/* CSS Document */\\n\\n/** Structure */\\nbody {\\n  font-family: Arial, sans-serif;\\n  margin: 0;\\n  font-size: 14px;\\n}\\n\\n#system-error {\\n  font-size: 1.5em;\\n  text-align: center;\\n}\\n\\n#json, #xml {\\n  display: none;\\n}\\n\\n#header {\\n  position: fixed;\\n  width: 100%;\\n}\\n\\n#specs {\\n  padding-top: 50px;\\n}\\n\\n#header .angular {\\n  font-family: Courier New, monospace;\\n  font-weight: bold;\\n}\\n\\n#header h1 {\\n  font-weight: normal;\\n  float: left;\\n  font-size: 30px;\\n  line-height: 30px;\\n  margin: 0;\\n  padding: 10px 10px;\\n  height: 30px;\\n}\\n\\n#application h2,\\n#specs h2 {\\n  margin: 0;\\n  padding: 0.5em;\\n  font-size: 1.1em;\\n}\\n\\n#status-legend {\\n  margin-top: 10px;\\n  margin-right: 10px;\\n}\\n\\n#header,\\n#application,\\n.test-info,\\n.test-actions li {\\n  overflow: hidden;\\n}\\n\\n#application {\\n  margin: 10px;\\n}\\n\\n#application iframe {\\n  width: 100%;\\n  height: 758px;\\n}\\n\\n#application .popout {\\n  float: right;\\n}\\n\\n#application iframe {\\n  border: none;\\n}\\n\\n.tests li,\\n.test-actions li,\\n.test-it li,\\n.test-it ol,\\n.status-display {\\n  list-style-type: none;\\n}\\n\\n.tests,\\n.test-it ol,\\n.status-display {\\n  margin: 0;\\n  padding: 0;\\n}\\n\\n.test-info {\\n  margin-left: 1em;\\n  margin-top: 0.5em;\\n  border-radius: 8px 0 0 8px;\\n  -webkit-border-radius: 8px 0 0 8px;\\n  -moz-border-radius: 8px 0 0 8px;\\n  cursor: pointer;\\n}\\n\\n.test-info:hover .test-name {\\n  text-decoration: underline;\\n}\\n\\n.test-info .closed:before {\\n  content: \\'\\\\25b8\\\\00A0\\';\\n}\\n\\n.test-info .open:before {\\n  content: \\'\\\\25be\\\\00A0\\';\\n  font-weight: bold;\\n}\\n\\n.test-it ol {\\n  margin-left: 2.5em;\\n}\\n\\n.status-display,\\n.status-display li {\\n  float: right;\\n}\\n\\n.status-display li {\\n  padding: 5px 10px;\\n}\\n\\n.timer-result,\\n.test-title {\\n  display: inline-block;\\n  margin: 0;\\n  padding: 4px;\\n}\\n\\n.test-actions .test-title,\\n.test-actions .test-result {\\n  display: table-cell;\\n  padding-left: 0.5em;\\n  padding-right: 0.5em;\\n}\\n\\n.test-actions {\\n  display: table;\\n}\\n\\n.test-actions li {\\n  display: table-row;\\n}\\n\\n.timer-result {\\n  width: 4em;\\n  padding: 0 10px;\\n  text-align: right;\\n  font-family: monospace;\\n}\\n\\n.test-it pre,\\n.test-actions pre {\\n  clear: left;\\n  color: black;\\n  margin-left: 6em;\\n}\\n\\n.test-describe {\\n  padding-bottom: 0.5em;\\n}\\n\\n.test-describe .test-describe {\\n  margin: 5px 5px 10px 2em;\\n}\\n\\n.test-actions .status-pending .test-title:before {\\n  content: \\'\\\\00bb\\\\00A0\\';\\n}\\n\\n.scrollpane {\\n   max-height: 20em;\\n   overflow: auto;\\n}\\n\\n/** Colors */\\n\\n#header {\\n  background-color: #F2C200;\\n}\\n\\n#specs h2 {\\n  border-top: 2px solid #BABAD1;\\n}\\n\\n#specs h2,\\n#application h2 {\\n  background-color: #efefef;\\n}\\n\\n#application {\\n  border: 1px solid #BABAD1;\\n}\\n\\n.test-describe .test-describe {\\n  border-left: 1px solid #BABAD1;\\n  border-right: 1px solid #BABAD1;\\n  border-bottom: 1px solid #BABAD1;\\n}\\n\\n.status-display {\\n  border: 1px solid #777;\\n}\\n\\n.status-display .status-pending,\\n.status-pending .test-info {\\n  background-color: #F9EEBC;\\n}\\n\\n.status-display .status-success,\\n.status-success .test-info {\\n  background-color: #B1D7A1;\\n}\\n\\n.status-display .status-failure,\\n.status-failure .test-info {\\n  background-color: #FF8286;\\n}\\n\\n.status-display .status-error,\\n.status-error .test-info {\\n  background-color: black;\\n  color: white;\\n}\\n\\n.test-actions .status-success .test-title {\\n  color: #30B30A;\\n}\\n\\n.test-actions .status-failure .test-title {\\n  color: #DF0000;\\n}\\n\\n.test-actions .status-error .test-title {\\n  color: black;\\n}\\n\\n.test-actions .timer-result {\\n  color: #888;\\n}\\n</style>');"
  },
  {
    "path": "chapter5/recipe5/test/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter5/recipe5/test/unit/controllersSpec.js",
    "content": "describe('MyCtrl', function(){\n  var scope, ctrl, httpBackend;\n\n  beforeEach(module(\"MyApp\"));\n\n  beforeEach(inject(function($controller, $rootScope, TwitterAPI, $httpBackend) {\n    httpBackend = $httpBackend;\n    scope = $rootScope.$new();\n    ctrl = $controller(\"MyCtrl\", { $scope: scope, TwitterAPI: TwitterAPI });\n\n    var mock_data = { key: \"test\" };\n    var url = \"http://search.twitter.com/search.json?callback=JSON_CALLBACK&q=angularjs\";\n    httpBackend.whenJSONP(url).respond(mock_data);\n  }));\n\n  it('should set searchResult on successful search', function() {\n    scope.searchTerm = \"angularjs\";\n    scope.search();\n    httpBackend.flush();\n\n    expect(scope.searchResult.key).toBe(\"test\");\n  });\n\n});"
  },
  {
    "path": "chapter6/recipe1/README.md",
    "content": "# angular-seed — the seed for AngularJS apps\n\nThis project is an application skeleton for a typical [AngularJS](http://angularjs.org/) web app.\nYou can use it to quickly bootstrap your angular webapp projects and dev environment for these\nprojects.\n\nThe seed contains AngularJS libraries, test libraries and a bunch of scripts all preconfigured for\ninstant web development gratification. Just clone the repo (or download the zip/tarball), start up\nour (or yours) webserver and you are ready to develop and test your application.\n\nThe seed app doesn't do much, just shows how to wire two controllers and views together. You can\ncheck it out by opening app/index.html in your browser (might not work file `file://` scheme in\ncertain browsers, see note below).\n\n_Note: While angular is client-side-only technology and it's possible to create angular webapps that\ndon't require a backend server at all, we recommend hosting the project files using a local\nwebserver during development to avoid issues with security restrictions (sandbox) in browsers. The\nsandbox implementation varies between browsers, but quite often prevents things like cookies, xhr,\netc to function properly when an html page is opened via `file://` scheme instead of `http://`._\n\n\n## How to use angular-seed\n\nClone the angular-seed repository and start hacking...\n\n\n### Running the app during development\n\nYou can pick one of these options:\n\n* serve this repository with your webserver\n* install node.js and run `scripts/web-server.js`\n\nThen navigate your browser to `http://localhost:<port>/app/index.html` to see the app running in\nyour browser.\n\n\n### Running the app in production\n\nThis really depends on how complex is your app and the overall infrastructure of your system, but\nthe general rule is that all you need in production are all the files under the `app/` directory.\nEverything else should be omitted.\n\nAngular apps are really just a bunch of static html, css and js files that just need to be hosted\nsomewhere, where they can be accessed by browsers.\n\nIf your Angular app is talking to the backend server via xhr or other means, you need to figure\nout what is the best way to host the static files to comply with the same origin policy if\napplicable. Usually this is done by hosting the files by the backend server or through\nreverse-proxying the backend server(s) and a webserver(s).\n\n\n### Running unit tests\n\nWe recommend using [jasmine](http://pivotal.github.com/jasmine/) and\n[Testacular](http://vojtajina.github.com/testacular/) for your unit tests/specs, but you are free\nto use whatever works for you.\n\nRequires [node.js](http://nodejs.org/), Testacular (`sudo npm install -g testacular`) and a local\nor remote browser.\n\n* start `scripts/test.sh` (on windows: `scripts\\test.bat`)\n  * a browser will start and connect to the Testacular server (Chrome is default browser, others can be captured by loading the same url as the one in Chrome or by changing the `config/testacular.conf.js` file)\n* to run or re-run tests just change any of your source or test javascript files\n\n\n### End to end testing\n\nAngular ships with a baked-in end-to-end test runner that understands angular, your app and allows\nyou to write your tests with jasmine-like BDD syntax.\n\nRequires a webserver, node.js + `./scripts/web-server.js` or your backend server that hosts the angular static files.\n\nCheck out the\n[end-to-end runner's documentation](http://docs.angularjs.org/guide/dev_guide.e2e-testing) for more\ninfo.\n\n* create your end-to-end tests in `test/e2e/scenarios.js`\n* serve your project directory with your http/backend server or node.js + `scripts/web-server.js`\n* to run do one of:\n  * open `http://localhost:port/test/e2e/runner.html` in your browser\n  * run the tests from console with [Testacular](vojtajina.github.com/testacular) via\n    `scripts/e2e-test.sh` or `script/e2e-test.bat`\n\n\n### Receiving updates from upstream\n\nWhen we upgrade angular-seed's repo with newer angular or testing library code, you can just\nfetch the changes and merge them into your project with git.\n\n\n## Directory Layout\n\n    app/                --> all of the files to be used in production\n      css/              --> css files\n        app.css         --> default stylesheet\n      img/              --> image files\n      index.html        --> app layout file (the main html template file of the app)\n      index-async.html  --> just like index.html, but loads js files asynchronously\n      js/               --> javascript files\n        app.js          --> application\n        controllers.js  --> application controllers\n        directives.js   --> application directives\n        filters.js      --> custom angular filters\n        services.js     --> custom angular services\n      lib/              --> angular and 3rd party javascript libraries\n        angular/\n          angular.js        --> the latest angular js\n          angular.min.js    --> the latest minified angular js\n          angular-*.js      --> angular add-on modules\n          version.txt       --> version number\n      partials/             --> angular view partials (partial html templates)\n        partial1.html\n        partial2.html\n\n    config/testacular.conf.js        --> config file for running unit tests with Testacular\n    config/testacular-e2e.conf.js    --> config file for running e2e tests with Testacular\n\n    scripts/            --> handy shell/js/ruby scripts\n      e2e-test.sh       --> runs end-to-end tests with Testacular (*nix)\n      e2e-test.bat      --> runs end-to-end tests with Testacular (windows)\n      test.bat          --> autotests unit tests with Testacular (windows)\n      test.sh           --> autotests unit tests with Testacular (*nix)\n      web-server.js     --> simple development webserver based on node.js\n\n    test/               --> test source files and libraries\n      e2e/              -->\n        runner.html     --> end-to-end test runner (open in your browser to run)\n        scenarios.js    --> end-to-end specs\n      lib/\n        angular/                --> angular testing libraries\n          angular-mocks.js      --> mocks that replace certain angular services in tests\n          angular-scenario.js   --> angular's scenario (end-to-end) test runner library\n          version.txt           --> version file\n      unit/                     --> unit level specs/tests\n        controllersSpec.js      --> specs for controllers\n        directivessSpec.js      --> specs for directives\n        filtersSpec.js          --> specs for filters\n        servicesSpec.js         --> specs for services\n\n## Contact\n\nFor more information on AngularJS please check out http://angularjs.org/\n"
  },
  {
    "path": "chapter6/recipe1/app/css/.gitignore",
    "content": ""
  },
  {
    "path": "chapter6/recipe1/app/css/app.css",
    "content": "/* app css stylesheet */\n\n.menu {\n  list-style: none;\n  border-bottom: 0.1em solid black;\n  margin-bottom: 2em;\n  padding: 0 0 0.5em;\n}\n\n.menu:before {\n  content: \"[\";\n}\n\n.menu:after {\n  content: \"]\";\n}\n\n.menu > li {\n  display: inline;\n}\n\n.menu > li:before {\n  content: \"|\";\n  padding-right: 0.3em;\n}\n\n.menu > li:nth-child(1):before {\n  content: \"\";\n  padding: 0;\n}\n"
  },
  {
    "path": "chapter6/recipe1/app/img/.gitignore",
    "content": ""
  },
  {
    "path": "chapter6/recipe1/app/index-async.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <style>\n    [ng-cloak] {\n      display: none;\n    }\n  </style>\n  <script>\n    // include angular loader, which allows the files to load in any order\n    /*\n     AngularJS v1.0.0rc1\n     (c) 2010-2012 AngularJS http://angularjs.org\n     License: MIT\n    */\n    'use strict';(function(i){function d(c,a,e){return c[a]||(c[a]=e())}return d(d(i,\"angular\",Object),\"module\",function(){var c={};return function(a,e,f){e&&c.hasOwnProperty(a)&&(c[a]=null);return d(c,a,function(){function b(a,b,d){return function(){c[d||\"push\"]([a,b,arguments]);return g}}if(!e)throw Error(\"No module: \"+a);var c=[],d=[],h=b(\"$injector\",\"invoke\"),g={_invokeQueue:c,_runBlocks:d,requires:e,name:a,provider:b(\"$provide\",\"provider\"),factory:b(\"$provide\",\"factory\"),service:b(\"$provide\",\"service\"),\n    value:b(\"$provide\",\"value\"),constant:b(\"$provide\",\"constant\",\"unshift\"),filter:b(\"$filterProvider\",\"register\"),directive:b(\"$compileProvider\",\"directive\"),config:h,run:function(a){d.push(a);return this}};f&&h(f);return g})}})})(window);\n\n    // include a third-party async loader library\n    /*!\n     * $script.js v1.3\n     * https://github.com/ded/script.js\n     * Copyright: @ded & @fat - Dustin Diaz, Jacob Thornton 2011\n     * Follow our software http://twitter.com/dedfat\n     * License: MIT\n     */\n    !function(a,b,c){function t(a,c){var e=b.createElement(\"script\"),f=j;e.onload=e.onerror=e[o]=function(){e[m]&&!/^c|loade/.test(e[m])||f||(e.onload=e[o]=null,f=1,c())},e.async=1,e.src=a,d.insertBefore(e,d.firstChild)}function q(a,b){p(a,function(a){return!b(a)})}var d=b.getElementsByTagName(\"head\")[0],e={},f={},g={},h={},i=\"string\",j=!1,k=\"push\",l=\"DOMContentLoaded\",m=\"readyState\",n=\"addEventListener\",o=\"onreadystatechange\",p=function(a,b){for(var c=0,d=a.length;c<d;++c)if(!b(a[c]))return j;return 1};!b[m]&&b[n]&&(b[n](l,function r(){b.removeEventListener(l,r,j),b[m]=\"complete\"},j),b[m]=\"loading\");var s=function(a,b,d){function o(){if(!--m){e[l]=1,j&&j();for(var a in g)p(a.split(\"|\"),n)&&!q(g[a],n)&&(g[a]=[])}}function n(a){return a.call?a():e[a]}a=a[k]?a:[a];var i=b&&b.call,j=i?b:d,l=i?a.join(\"\"):b,m=a.length;c(function(){q(a,function(a){h[a]?(l&&(f[l]=1),o()):(h[a]=1,l&&(f[l]=1),t(s.path?s.path+a+\".js\":a,o))})},0);return s};s.get=t,s.ready=function(a,b,c){a=a[k]?a:[a];var d=[];!q(a,function(a){e[a]||d[k](a)})&&p(a,function(a){return e[a]})?b():!function(a){g[a]=g[a]||[],g[a][k](b),c&&c(d)}(a.join(\"|\"));return s};var u=a.$script;s.noConflict=function(){a.$script=u;return this},typeof module!=\"undefined\"&&module.exports?module.exports=s:a.$script=s}(this,document,setTimeout)\n\n    // load all of the dependencies asynchronously.\n    $script([\n      'lib/angular/angular.js',\n      'js/app.js',\n      'js/services.js',\n      'js/controllers.js',\n      'js/filters.js',\n      'js/directives.js'\n    ], function() {\n      // when all is done, execute bootstrap angular application\n      angular.bootstrap(document, ['myApp']);\n    });\n  </script>\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\">\n</head>\n<body ng-cloak>\n  <ul class=\"menu\">\n    <li><a href=\"#/view1\">view1</a></li>\n    <li><a href=\"#/view2\">view2</a></li>\n  </ul>\n\n  <div ng-view></div>\n\n  <div>Angular seed app: v<span app-version></span></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "chapter6/recipe1/app/index.html",
    "content": "<!doctype html>\n<html lang=\"en\" ng-app=\"MyApp\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\"/>\n</head>\n<body>\n  <h1>Routing Example</h1>\n  <ng-view></ng-view>\n  <script src=\"lib/angular/angular.js\"></script>\n  <script src=\"js/app.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "chapter6/recipe1/app/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []).\n  config(function($routeProvider, $locationProvider) {\n    $locationProvider.hashPrefix('!');\n    $routeProvider.\n      when(\"/persons\", { templateUrl: \"partials/person_list.html\" }).\n      when(\"/persons/:id\", { templateUrl: \"partials/person_details.html\", controller: \"ShowCtrl\" }).\n      otherwise( { redirectTo: \"/persons\" });\n});\n\n\napp.factory(\"Person\", function() {\n\n  var persons = [\n    { name: \"Peter\", age: 25, id: 1 },\n    { name: \"Stefan\", age: 35, id: 2 },\n    { name: \"Agnes\", age: 22, id: 3 }\n  ];\n\n  return {\n    all: function() {\n      return persons;\n    },\n    get: function(id) {\n      var result = null;\n      angular.forEach(persons, function(p) {\n        if (p.id == id) result = p;\n      });\n      return result;\n    }\n  };\n});\n\napp.controller(\"IndexCtrl\", function($scope, Person) {\n  $scope.persons = Person.all();\n});\n\napp.controller(\"ShowCtrl\", function($scope, $routeParams, Person) {\n  $scope.person = Person.get($routeParams.id);\n});"
  },
  {
    "path": "chapter6/recipe1/app/lib/angular/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngCookies\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookies\n   * @requires $browser\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from\n   * this object, new cookies are created/deleted at the end of current $eval.\n   *\n   * @example\n   */\n   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for(name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            if (angular.isDefined(lastCookies[name])) {\n              cookies[name] = lastCookies[name];\n            } else {\n              delete cookies[name];\n            }\n          } else if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated){\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   * @example\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#get\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          return angular.fromJson($cookies[key]);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#put\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#remove\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter6/recipe1/app/lib/angular/angular-loader.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n\n(\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n'use strict';\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n)(window);\n\n/**\n * Closure compiler type information\n *\n * @typedef { {\n *   requires: !Array.<string>,\n *   invokeQueue: !Array.<Array.<*>>,\n *\n *   service: function(string, Function):angular.Module,\n *   factory: function(string, Function):angular.Module,\n *   value: function(string, *):angular.Module,\n *\n *   filter: function(string, Function):angular.Module,\n *\n *   init: function(Function):angular.Module\n * } }\n */\nangular.Module;\n\n"
  },
  {
    "path": "chapter6/recipe1/app/lib/angular/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g. \n *   `http://example.com:8080/api`), you'll need to escape the colon character before the port\n *   number, like this: `$resource('http://example.com\\\\:8080/api')`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` – {string} – The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` – {object=} – Optional set of pre-bound parameters for this action.\n *   - isArray – {boolean=} – If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n     * encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace((pctEncodeSpaces ? null : /%20/g), '+');\n    }\n\n    function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        action.method = angular.uppercase(action.method);\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter6/recipe1/app/lib/angular/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             '<p style=\"color:blue\">an html\\n' +\n             '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n             'snippet</p>';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n          Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n           <table>\n             <tr>\n               <td>Filter</td>\n               <td>Source</td>\n               <td>Rendered</td>\n             </tr>\n             <tr id=\"html-filter\">\n               <td>html filter</td>\n               <td>\n                 <pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre>\n               </td>\n               <td>\n                 <div ng-bind-html=\"snippet\"></div>\n               </td>\n             </tr>\n             <tr id=\"escaped-html\">\n               <td>no filter</td>\n               <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind=\"snippet\"></div></td>\n             </tr>\n             <tr id=\"html-unsafe-filter\">\n               <td>unsafe html filter</td>\n               <td><pre>&lt;div ng-bind-html-unsafe=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind-html-unsafe=\"snippet\"></div></td>\n             </tr>\n           </table>\n         </div>\n     </doc:source>\n     <doc:scenario>\n       it('should sanitize the html snippet ', function() {\n         expect(using('#html-filter').element('div').html()).\n           toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n       });\n\n       it('should escape snippet without any filter', function() {\n         expect(using('#escaped-html').element('div').html()).\n           toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n                \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n                \"snippet&lt;/p&gt;\");\n       });\n\n       it('should inline raw snippet if filtered as unsafe', function() {\n         expect(using('#html-unsafe-filter').element(\"div\").html()).\n           toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n                \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n                \"snippet</p>\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new <b>text</b>');\n         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');\n         expect(using('#escaped-html').element('div').html()).toBe(\"new &lt;b&gt;text&lt;/b&gt;\");\n         expect(using('#html-unsafe-filter').binding(\"snippet\")).toBe('new <b>text</b>');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar $sanitize = function(html) {\n  var buf = [];\n    htmlParser(html, htmlSanitizeWriter(buf));\n    return buf.join('');\n};\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP = /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  URI_REGEXP = /^((ftp|https?):\\/\\/|mailto:|#)/,\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g; // Match everything outside of normal chars and \" (quote character)\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,aside,\" +\n        \"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,\" +\n        \"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,bdi,bdo,\" +\n        \"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,\" +\n        \"span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        index = html.indexOf(\"-->\");\n\n        if ( index >= 0 ) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'), function(all, text){\n        text = text.\n          replace(COMMENT_REGEXP, \"$1\").\n          replace(CDATA_REGEXP, \"$1\");\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n\n        return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw \"Parse Error: \" + html;\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {\n      var value = doubleQuotedValue\n        || singleQoutedValue\n        || unqoutedValue\n        || '';\n\n      attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nvar hiddenPre=document.createElement(\"pre\");\nfunction decodeEntities(value) {\n  hiddenPre.innerHTML=value.replace(/</g,\"&lt;\");\n  return hiddenPre.innerText || hiddenPre.textContent || '';\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] == true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] == true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).value('$sanitize', $sanitize);\n\n/**\n * @ngdoc directive\n * @name ngSanitize.directive:ngBindHtml\n *\n * @description\n * Creates a binding that will sanitize the result of evaluating the `expression` with the\n * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n */\nangular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);\n    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {\n      value = $sanitize(value);\n      element.html(value || '');\n    });\n  };\n}]);\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n *   plain email address links.\n *\n * @param {string} text Input text.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should linkify the snippet with urls', function() {\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('Pretty text with some links:&#10;' +\n                '<a href=\"http://angularjs.org/\">http://angularjs.org/</a>,&#10;' +\n                '<a href=\"mailto:us@somewhere.org\">us@somewhere.org</a>,&#10;' +\n                '<a href=\"mailto:another@somewhere.org\">another@somewhere.org</a>,&#10;' +\n                'and one more: <a href=\"ftp://127.0.0.1/\">ftp://127.0.0.1/</a>.');\n       });\n\n       it ('should not linkify snippet without the linky filter', function() {\n         expect(using('#escaped-html').binding('snippet')).\n           toBe(\"Pretty text with some links:\\n\" +\n                \"http://angularjs.org/,\\n\" +\n                \"mailto:us@somewhere.org,\\n\" +\n                \"another@somewhere.org,\\n\" +\n                \"and one more: ftp://127.0.0.1/.\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new http://link.');\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('new <a href=\"http://link\">http://link</a>.');\n         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', function() {\n  var LINKY_URL_REGEXP = /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s\\.\\;\\,\\(\\)\\{\\}\\<\\>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    // TODO(vojta): use $sanitize instead\n    var writer = htmlSanitizeWriter(html);\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      writer.chars(raw.substr(0, i));\n      writer.start('a', {href:url});\n      writer.chars(match[0].replace(MAILTO_REGEXP, ''));\n      writer.end('a');\n      raw = raw.substring(i + match[0].length);\n    }\n    writer.chars(raw);\n    return html.join('');\n  };\n});\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter6/recipe1/app/lib/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter6/recipe1/app/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter6/recipe1/app/partials/.gitignore",
    "content": ""
  },
  {
    "path": "chapter6/recipe1/app/partials/person_details.html",
    "content": "<h3>{{person.name}} Details</h3>\n<p>Name: {{person.name}}</p>\n<p>Age: {{person.age}}</p>\n\n<a href=\"#!persons\">Go back</a>"
  },
  {
    "path": "chapter6/recipe1/app/partials/person_list.html",
    "content": "<h3>Person List</h3>\n<div ng-controller=\"IndexCtrl\">\n  <table>\n    <thead>\n      <tr>\n        <td>Name</td>\n        <td>Actions</td>\n      </tr>\n    </thead>\n    <tbody>\n      <tr ng-repeat=\"person in persons\">\n        <td>{{person.name}}</td>\n        <td><a href=\"#!persons/{{person.id}}\">Details</a></td>\n      </tr>\n    </tbody>\n  </table>\n</div>\n"
  },
  {
    "path": "chapter6/recipe1/config/testacular-e2e.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  ANGULAR_SCENARIO,\n  ANGULAR_SCENARIO_ADAPTER,\n  'test/e2e/**/*.js'\n];\n\nautoWatch = false;\n\nbrowsers = ['Chrome'];\n\nsingleRun = true;\n\nproxies = {\n  '/': 'http://localhost:8000/'\n};\n\njunitReporter = {\n  outputFile: 'test_out/e2e.xml',\n  suite: 'e2e'\n};\n"
  },
  {
    "path": "chapter6/recipe1/config/testacular.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  JASMINE,\n  JASMINE_ADAPTER,\n  'app/lib/angular/angular.js',\n  'app/lib/angular/angular-*.js',\n  'test/lib/angular/angular-mocks.js',\n  'app/js/**/*.js',\n  'test/unit/**/*.js'\n];\n\nautoWatch = true;\n\nbrowsers = ['Chrome'];\n\njunitReporter = {\n  outputFile: 'test_out/unit.xml',\n  suite: 'unit'\n};\n"
  },
  {
    "path": "chapter6/recipe1/logs/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "chapter6/recipe1/scripts/e2e-test.bat",
    "content": "@echo off\n\nREM Windows script for running e2e tests\nREM You have to run server and capture some browser first\nREM\nREM Requirements:\nREM - NodeJS (http://nodejs.org/)\nREM - Testacular (npm install -g testacular)\n\nset BASE_DIR=%~dp0\ntestacular start \"%BASE_DIR%\\..\\config\\testacular-e2e.conf.js\" %*\n"
  },
  {
    "path": "chapter6/recipe1/scripts/e2e-test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular-e2e.conf.js $*\n"
  },
  {
    "path": "chapter6/recipe1/scripts/test.bat",
    "content": "@echo off\r\n\r\nREM Windows script for running unit tests\r\nREM You have to run server and capture some browser first\r\nREM\r\nREM Requirements:\r\nREM - NodeJS (http://nodejs.org/)\r\nREM - Testacular (npm install -g testacular)\r\n\r\nset BASE_DIR=%~dp0\r\ntestacular start \"%BASE_DIR%\\..\\config\\testacular.conf.js\" %*\r\n"
  },
  {
    "path": "chapter6/recipe1/scripts/test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular.conf.js $*\n"
  },
  {
    "path": "chapter6/recipe1/scripts/watchr.rb",
    "content": "#!/usr/bin/env watchr\n\n# config file for watchr http://github.com/mynyml/watchr\n# install: gem install watchr\n# run: watch watchr.rb\n# note: make sure that you have jstd server running (server.sh) and a browser captured\n\nlog_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log')\n\n`cd ..`\n`touch #{log_file}`\n\nputs \"String watchr... log file: #{log_file}\"\n\nwatch( '(app/js|test/unit)' )  do\n  `echo \"\\n\\ntest run started @ \\`date\\`\" > #{log_file}`\n  `scripts/test.sh &> #{log_file}`\nend\n\n"
  },
  {
    "path": "chapter6/recipe1/scripts/web-server.js",
    "content": "#!/usr/bin/env node\n\nvar util = require('util'),\n    http = require('http'),\n    fs = require('fs'),\n    url = require('url'),\n    events = require('events');\n\nvar DEFAULT_PORT = 8000;\n\nfunction main(argv) {\n  new HttpServer({\n    'GET': createServlet(StaticServlet),\n    'HEAD': createServlet(StaticServlet)\n  }).start(Number(argv[2]) || DEFAULT_PORT);\n}\n\nfunction escapeHtml(value) {\n  return value.toString().\n    replace('<', '&lt;').\n    replace('>', '&gt;').\n    replace('\"', '&quot;');\n}\n\nfunction createServlet(Class) {\n  var servlet = new Class();\n  return servlet.handleRequest.bind(servlet);\n}\n\n/**\n * An Http server implementation that uses a map of methods to decide\n * action routing.\n *\n * @param {Object} Map of method => Handler function\n */\nfunction HttpServer(handlers) {\n  this.handlers = handlers;\n  this.server = http.createServer(this.handleRequest_.bind(this));\n}\n\nHttpServer.prototype.start = function(port) {\n  this.port = port;\n  this.server.listen(port);\n  util.puts('Http Server running at http://localhost:' + port + '/');\n};\n\nHttpServer.prototype.parseUrl_ = function(urlString) {\n  var parsed = url.parse(urlString);\n  parsed.pathname = url.resolve('/', parsed.pathname);\n  return url.parse(url.format(parsed), true);\n};\n\nHttpServer.prototype.handleRequest_ = function(req, res) {\n  var logEntry = req.method + ' ' + req.url;\n  if (req.headers['user-agent']) {\n    logEntry += ' ' + req.headers['user-agent'];\n  }\n  util.puts(logEntry);\n  req.url = this.parseUrl_(req.url);\n  var handler = this.handlers[req.method];\n  if (!handler) {\n    res.writeHead(501);\n    res.end();\n  } else {\n    handler.call(this, req, res);\n  }\n};\n\n/**\n * Handles static content.\n */\nfunction StaticServlet() {}\n\nStaticServlet.MimeMap = {\n  'txt': 'text/plain',\n  'html': 'text/html',\n  'css': 'text/css',\n  'xml': 'application/xml',\n  'json': 'application/json',\n  'js': 'application/javascript',\n  'jpg': 'image/jpeg',\n  'jpeg': 'image/jpeg',\n  'gif': 'image/gif',\n  'png': 'image/png',\n  'svg': 'image/svg+xml'\n};\n\nStaticServlet.prototype.handleRequest = function(req, res) {\n  var self = this;\n  var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){\n    return String.fromCharCode(parseInt(hex, 16));\n  });\n  var parts = path.split('/');\n  if (parts[parts.length-1].charAt(0) === '.')\n    return self.sendForbidden_(req, res, path);\n  fs.stat(path, function(err, stat) {\n    if (err)\n      return self.sendMissing_(req, res, path);\n    if (stat.isDirectory())\n      return self.sendDirectory_(req, res, path);\n    return self.sendFile_(req, res, path);\n  });\n}\n\nStaticServlet.prototype.sendError_ = function(req, res, error) {\n  res.writeHead(500, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>Internal Server Error</title>\\n');\n  res.write('<h1>Internal Server Error</h1>');\n  res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');\n  util.puts('500 Internal Server Error');\n  util.puts(util.inspect(error));\n};\n\nStaticServlet.prototype.sendMissing_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(404, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>404 Not Found</title>\\n');\n  res.write('<h1>Not Found</h1>');\n  res.write(\n    '<p>The requested URL ' +\n    escapeHtml(path) +\n    ' was not found on this server.</p>'\n  );\n  res.end();\n  util.puts('404 Not Found: ' + path);\n};\n\nStaticServlet.prototype.sendForbidden_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(403, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>403 Forbidden</title>\\n');\n  res.write('<h1>Forbidden</h1>');\n  res.write(\n    '<p>You do not have permission to access ' +\n    escapeHtml(path) + ' on this server.</p>'\n  );\n  res.end();\n  util.puts('403 Forbidden: ' + path);\n};\n\nStaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {\n  res.writeHead(301, {\n      'Content-Type': 'text/html',\n      'Location': redirectUrl\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>301 Moved Permanently</title>\\n');\n  res.write('<h1>Moved Permanently</h1>');\n  res.write(\n    '<p>The document has moved <a href=\"' +\n    redirectUrl +\n    '\">here</a>.</p>'\n  );\n  res.end();\n  util.puts('301 Moved Permanently: ' + redirectUrl);\n};\n\nStaticServlet.prototype.sendFile_ = function(req, res, path) {\n  var self = this;\n  var file = fs.createReadStream(path);\n  res.writeHead(200, {\n    'Content-Type': StaticServlet.\n      MimeMap[path.split('.').pop()] || 'text/plain'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n  } else {\n    file.on('data', res.write.bind(res));\n    file.on('close', function() {\n      res.end();\n    });\n    file.on('error', function(error) {\n      self.sendError_(req, res, error);\n    });\n  }\n};\n\nStaticServlet.prototype.sendDirectory_ = function(req, res, path) {\n  var self = this;\n  if (path.match(/[^\\/]$/)) {\n    req.url.pathname += '/';\n    var redirectUrl = url.format(url.parse(url.format(req.url)));\n    return self.sendRedirect_(req, res, redirectUrl);\n  }\n  fs.readdir(path, function(err, files) {\n    if (err)\n      return self.sendError_(req, res, error);\n\n    if (!files.length)\n      return self.writeDirectoryIndex_(req, res, path, []);\n\n    var remaining = files.length;\n    files.forEach(function(fileName, index) {\n      fs.stat(path + '/' + fileName, function(err, stat) {\n        if (err)\n          return self.sendError_(req, res, err);\n        if (stat.isDirectory()) {\n          files[index] = fileName + '/';\n        }\n        if (!(--remaining))\n          return self.writeDirectoryIndex_(req, res, path, files);\n      });\n    });\n  });\n};\n\nStaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {\n  path = path.substring(1);\n  res.writeHead(200, {\n    'Content-Type': 'text/html'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n    return;\n  }\n  res.write('<!doctype html>\\n');\n  res.write('<title>' + escapeHtml(path) + '</title>\\n');\n  res.write('<style>\\n');\n  res.write('  ol { list-style-type: none; font-size: 1.2em; }\\n');\n  res.write('</style>\\n');\n  res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');\n  res.write('<ol>');\n  files.forEach(function(fileName) {\n    if (fileName.charAt(0) !== '.') {\n      res.write('<li><a href=\"' +\n        escapeHtml(fileName) + '\">' +\n        escapeHtml(fileName) + '</a></li>');\n    }\n  });\n  res.write('</ol>');\n  res.end();\n};\n\n// Must be last,\nmain(process.argv);\n"
  },
  {
    "path": "chapter6/recipe1/test/e2e/runner.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <title>End2end Test Runner</title>\n    <script src=\"../lib/angular/angular-scenario.js\" ng-autotest></script>\n    <script src=\"scenarios.js\"></script>\n  </head>\n  <body>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter6/recipe1/test/e2e/scenarios.js",
    "content": "'use strict';\n\n/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */\n\ndescribe('my app', function() {\n\n  beforeEach(function() {\n    browser().navigateTo('../../app/index.html');\n  });\n\n\n  it('should automatically redirect to /view1 when location hash/fragment is empty', function() {\n    expect(browser().location().url()).toBe(\"/view1\");\n  });\n\n\n  describe('view1', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view1');\n    });\n\n\n    it('should render view1 when user navigates to /view1', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 1/);\n    });\n\n  });\n\n\n  describe('view2', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view2');\n    });\n\n\n    it('should render view2 when user navigates to /view2', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 2/);\n    });\n\n  });\n});\n"
  },
  {
    "path": "chapter6/recipe1/test/lib/angular/angular-mocks.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n *\n * TODO(vojta): wrap whole file into closure during build\n */\n\n/**\n * @ngdoc overview\n * @name angular.mock\n * @description\n *\n * Namespace from 'angular-mocks.js' which contains testing related code.\n */\nangular.mock = {};\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ngMock.$browser\n *\n * @description\n * This service is a mock implementation of {@link ng.$browser}. It provides fake\n * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,\n * cookies, etc...\n *\n * The api of this service is the same as that of the real {@link ng.$browser $browser}, except\n * that there are several helper methods available which can be used in tests.\n */\nangular.mock.$BrowserProvider = function() {\n  this.$get = function(){\n    return new angular.mock.$Browser();\n  };\n};\n\nangular.mock.$Browser = function() {\n  var self = this;\n\n  this.isMock = true;\n  self.$$url = \"http://server/\";\n  self.$$lastUrl = self.$$url; // used by url polling fn\n  self.pollFns = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = angular.noop;\n  self.$$incOutstandingRequestCount = angular.noop;\n\n\n  // register url polling fn\n\n  self.onUrlChange = function(listener) {\n    self.pollFns.push(\n      function() {\n        if (self.$$lastUrl != self.$$url) {\n          self.$$lastUrl = self.$$url;\n          listener(self.$$url);\n        }\n      }\n    );\n\n    return listener;\n  };\n\n  self.cookieHash = {};\n  self.lastCookieHash = {};\n  self.deferredFns = [];\n  self.deferredNextId = 0;\n\n  self.defer = function(fn, delay) {\n    delay = delay || 0;\n    self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});\n    self.deferredFns.sort(function(a,b){ return a.time - b.time;});\n    return self.deferredNextId++;\n  };\n\n\n  self.defer.now = 0;\n\n\n  self.defer.cancel = function(deferId) {\n    var fnIndex;\n\n    angular.forEach(self.deferredFns, function(fn, index) {\n      if (fn.id === deferId) fnIndex = index;\n    });\n\n    if (fnIndex !== undefined) {\n      self.deferredFns.splice(fnIndex, 1);\n      return true;\n    }\n\n    return false;\n  };\n\n\n  /**\n   * @name ngMock.$browser#defer.flush\n   * @methodOf ngMock.$browser\n   *\n   * @description\n   * Flushes all pending requests and executes the defer callbacks.\n   *\n   * @param {number=} number of milliseconds to flush. See {@link #defer.now}\n   */\n  self.defer.flush = function(delay) {\n    if (angular.isDefined(delay)) {\n      self.defer.now += delay;\n    } else {\n      if (self.deferredFns.length) {\n        self.defer.now = self.deferredFns[self.deferredFns.length-1].time;\n      } else {\n        throw Error('No deferred tasks to be flushed');\n      }\n    }\n\n    while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {\n      self.deferredFns.shift().fn();\n    }\n  };\n  /**\n   * @name ngMock.$browser#defer.now\n   * @propertyOf ngMock.$browser\n   *\n   * @description\n   * Current milliseconds mock time.\n   */\n\n  self.$$baseHref = '';\n  self.baseHref = function() {\n    return this.$$baseHref;\n  };\n};\nangular.mock.$Browser.prototype = {\n\n/**\n  * @name ngMock.$browser#poll\n  * @methodOf ngMock.$browser\n  *\n  * @description\n  * run all fns in pollFns\n  */\n  poll: function poll() {\n    angular.forEach(this.pollFns, function(pollFn){\n      pollFn();\n    });\n  },\n\n  addPollFn: function(pollFn) {\n    this.pollFns.push(pollFn);\n    return pollFn;\n  },\n\n  url: function(url, replace) {\n    if (url) {\n      this.$$url = url;\n      return this;\n    }\n\n    return this.$$url;\n  },\n\n  cookies:  function(name, value) {\n    if (name) {\n      if (value == undefined) {\n        delete this.cookieHash[name];\n      } else {\n        if (angular.isString(value) &&       //strings only\n            value.length <= 4096) {          //strict cookie storage limits\n          this.cookieHash[name] = value;\n        }\n      }\n    } else {\n      if (!angular.equals(this.cookieHash, this.lastCookieHash)) {\n        this.lastCookieHash = angular.copy(this.cookieHash);\n        this.cookieHash = angular.copy(this.cookieHash);\n      }\n      return this.cookieHash;\n    }\n  },\n\n  notifyWhenNoOutstandingRequests: function(fn) {\n    fn();\n  }\n};\n\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandlerProvider\n *\n * @description\n * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed\n * into the `$exceptionHandler`.\n */\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandler\n *\n * @description\n * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed\n * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration\n * information.\n *\n *\n * <pre>\n *   describe('$exceptionHandlerProvider', function() {\n *\n *     it('should capture log messages and exceptions', function() {\n *\n *       module(function($exceptionHandlerProvider) {\n *         $exceptionHandlerProvider.mode('log');\n *       });\n *\n *       inject(function($log, $exceptionHandler, $timeout) {\n *         $timeout(function() { $log.log(1); });\n *         $timeout(function() { $log.log(2); throw 'banana peel'; });\n *         $timeout(function() { $log.log(3); });\n *         expect($exceptionHandler.errors).toEqual([]);\n *         expect($log.assertEmpty());\n *         $timeout.flush();\n *         expect($exceptionHandler.errors).toEqual(['banana peel']);\n *         expect($log.log.logs).toEqual([[1], [2], [3]]);\n *       });\n *     });\n *   });\n * </pre>\n */\n\nangular.mock.$ExceptionHandlerProvider = function() {\n  var handler;\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$exceptionHandlerProvider#mode\n   * @methodOf ngMock.$exceptionHandlerProvider\n   *\n   * @description\n   * Sets the logging mode.\n   *\n   * @param {string} mode Mode of operation, defaults to `rethrow`.\n   *\n   *   - `rethrow`: If any errors are are passed into the handler in tests, it typically\n   *                means that there is a bug in the application or test, so this mock will\n   *                make these tests fail.\n   *   - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores an\n   *            array of errors in `$exceptionHandler.errors`, to allow later assertion of them.\n   *            See {@link ngMock.$log#assertEmpty assertEmpty()} and\n   *             {@link ngMock.$log#reset reset()}\n   */\n  this.mode = function(mode) {\n    switch(mode) {\n      case 'rethrow':\n        handler = function(e) {\n          throw e;\n        };\n        break;\n      case 'log':\n        var errors = [];\n\n        handler = function(e) {\n          if (arguments.length == 1) {\n            errors.push(e);\n          } else {\n            errors.push([].slice.call(arguments, 0));\n          }\n        };\n\n        handler.errors = errors;\n        break;\n      default:\n        throw Error(\"Unknown mode '\" + mode + \"', only 'log'/'rethrow' modes are allowed!\");\n    }\n  };\n\n  this.$get = function() {\n    return handler;\n  };\n\n  this.mode('rethrow');\n};\n\n\n/**\n * @ngdoc service\n * @name ngMock.$log\n *\n * @description\n * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays\n * (one array per logging level). These arrays are exposed as `logs` property of each of the\n * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.\n *\n */\nangular.mock.$LogProvider = function() {\n\n  function concat(array1, array2, index) {\n    return array1.concat(Array.prototype.slice.call(array2, index));\n  }\n\n\n  this.$get = function () {\n    var $log = {\n      log: function() { $log.log.logs.push(concat([], arguments, 0)); },\n      warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },\n      info: function() { $log.info.logs.push(concat([], arguments, 0)); },\n      error: function() { $log.error.logs.push(concat([], arguments, 0)); }\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#reset\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Reset all of the logging arrays to empty.\n     */\n    $log.reset = function () {\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#log.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.log.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#warn.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.warn.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#info.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.info.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#error.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.error.logs = [];\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#assertEmpty\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.\n     */\n    $log.assertEmpty = function() {\n      var errors = [];\n      angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {\n        angular.forEach($log[logLevel].logs, function(log) {\n          angular.forEach(log, function (logItem) {\n            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\\n' + (logItem.stack || ''));\n          });\n        });\n      });\n      if (errors.length) {\n        errors.unshift(\"Expected $log to be empty! Either a message was logged unexpectedly, or an expected \" +\n          \"log message was not checked and removed:\");\n        errors.push('');\n        throw new Error(errors.join('\\n---------\\n'));\n      }\n    };\n\n    $log.reset();\n    return $log;\n  };\n};\n\n\n(function() {\n  var R_ISO8061_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?:\\:?(\\d\\d)(?:\\:?(\\d\\d)(?:\\.(\\d{3}))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d)))?$/;\n\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8061_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n  function int(str) {\n    return parseInt(str, 10);\n  }\n\n  function padNumber(num, digits, trim) {\n    var neg = '';\n    if (num < 0) {\n      neg =  '-';\n      num = -num;\n    }\n    num = '' + num;\n    while(num.length < digits) num = '0' + num;\n    if (trim)\n      num = num.substr(num.length - digits);\n    return neg + num;\n  }\n\n\n  /**\n   * @ngdoc object\n   * @name angular.mock.TzDate\n   * @description\n   *\n   * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.\n   *\n   * Mock of the Date type which has its timezone specified via constroctor arg.\n   *\n   * The main purpose is to create Date-like instances with timezone fixed to the specified timezone\n   * offset, so that we can test code that depends on local timezone settings without dependency on\n   * the time zone settings of the machine where the code is running.\n   *\n   * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)\n   * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*\n   *\n   * @example\n   * !!!! WARNING !!!!!\n   * This is not a complete Date object so only methods that were implemented can be called safely.\n   * To make matters worse, TzDate instances inherit stuff from Date via a prototype.\n   *\n   * We do our best to intercept calls to \"unimplemented\" methods, but since the list of methods is\n   * incomplete we might be missing some non-standard methods. This can result in errors like:\n   * \"Date.prototype.foo called on incompatible Object\".\n   *\n   * <pre>\n   * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');\n   * newYearInBratislava.getTimezoneOffset() => -60;\n   * newYearInBratislava.getFullYear() => 2010;\n   * newYearInBratislava.getMonth() => 0;\n   * newYearInBratislava.getDate() => 1;\n   * newYearInBratislava.getHours() => 0;\n   * newYearInBratislava.getMinutes() => 0;\n   * </pre>\n   *\n   */\n  angular.mock.TzDate = function (offset, timestamp) {\n    var self = new Date(0);\n    if (angular.isString(timestamp)) {\n      var tsStr = timestamp;\n\n      self.origDate = jsonStringToDate(timestamp);\n\n      timestamp = self.origDate.getTime();\n      if (isNaN(timestamp))\n        throw {\n          name: \"Illegal Argument\",\n          message: \"Arg '\" + tsStr + \"' passed into TzDate constructor is not a valid date string\"\n        };\n    } else {\n      self.origDate = new Date(timestamp);\n    }\n\n    var localOffset = new Date(timestamp).getTimezoneOffset();\n    self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;\n    self.date = new Date(timestamp + self.offsetDiff);\n\n    self.getTime = function() {\n      return self.date.getTime() - self.offsetDiff;\n    };\n\n    self.toLocaleDateString = function() {\n      return self.date.toLocaleDateString();\n    };\n\n    self.getFullYear = function() {\n      return self.date.getFullYear();\n    };\n\n    self.getMonth = function() {\n      return self.date.getMonth();\n    };\n\n    self.getDate = function() {\n      return self.date.getDate();\n    };\n\n    self.getHours = function() {\n      return self.date.getHours();\n    };\n\n    self.getMinutes = function() {\n      return self.date.getMinutes();\n    };\n\n    self.getSeconds = function() {\n      return self.date.getSeconds();\n    };\n\n    self.getTimezoneOffset = function() {\n      return offset * 60;\n    };\n\n    self.getUTCFullYear = function() {\n      return self.origDate.getUTCFullYear();\n    };\n\n    self.getUTCMonth = function() {\n      return self.origDate.getUTCMonth();\n    };\n\n    self.getUTCDate = function() {\n      return self.origDate.getUTCDate();\n    };\n\n    self.getUTCHours = function() {\n      return self.origDate.getUTCHours();\n    };\n\n    self.getUTCMinutes = function() {\n      return self.origDate.getUTCMinutes();\n    };\n\n    self.getUTCSeconds = function() {\n      return self.origDate.getUTCSeconds();\n    };\n\n    self.getUTCMilliseconds = function() {\n      return self.origDate.getUTCMilliseconds();\n    };\n\n    self.getDay = function() {\n      return self.date.getDay();\n    };\n\n    // provide this method only on browsers that already have it\n    if (self.toISOString) {\n      self.toISOString = function() {\n        return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +\n              padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +\n              padNumber(self.origDate.getUTCDate(), 2) + 'T' +\n              padNumber(self.origDate.getUTCHours(), 2) + ':' +\n              padNumber(self.origDate.getUTCMinutes(), 2) + ':' +\n              padNumber(self.origDate.getUTCSeconds(), 2) + '.' +\n              padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'\n      }\n    }\n\n    //hide all methods not implemented in this mock that the Date prototype exposes\n    var unimplementedMethods = ['getMilliseconds', 'getUTCDay',\n        'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',\n        'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',\n        'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',\n        'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',\n        'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];\n\n    angular.forEach(unimplementedMethods, function(methodName) {\n      self[methodName] = function() {\n        throw Error(\"Method '\" + methodName + \"' is not implemented in the TzDate mock\");\n      };\n    });\n\n    return self;\n  };\n\n  //make \"tzDateInstance instanceof Date\" return true\n  angular.mock.TzDate.prototype = Date.prototype;\n})();\n\n\n/**\n * @ngdoc function\n * @name angular.mock.dump\n * @description\n *\n * *NOTE*: this is not an injectable instance, just a globally available function.\n *\n * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.\n *\n * This method is also available on window, where it can be used to display objects on debug console.\n *\n * @param {*} object - any object to turn into string.\n * @return {string} a serialized string of the argument\n */\nangular.mock.dump = function(object) {\n  return serialize(object);\n\n  function serialize(object) {\n    var out;\n\n    if (angular.isElement(object)) {\n      object = angular.element(object);\n      out = angular.element('<div></div>');\n      angular.forEach(object, function(element) {\n        out.append(angular.element(element).clone());\n      });\n      out = out.html();\n    } else if (angular.isArray(object)) {\n      out = [];\n      angular.forEach(object, function(o) {\n        out.push(serialize(o));\n      });\n      out = '[ ' + out.join(', ') + ' ]';\n    } else if (angular.isObject(object)) {\n      if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {\n        out = serializeScope(object);\n      } else if (object instanceof Error) {\n        out = object.stack || ('' + object.name + ': ' + object.message);\n      } else {\n        out = angular.toJson(object, true);\n      }\n    } else {\n      out = String(object);\n    }\n\n    return out;\n  }\n\n  function serializeScope(scope, offset) {\n    offset = offset ||  '  ';\n    var log = [offset + 'Scope(' + scope.$id + '): {'];\n    for ( var key in scope ) {\n      if (scope.hasOwnProperty(key) && !key.match(/^(\\$|this)/)) {\n        log.push('  ' + key + ': ' + angular.toJson(scope[key]));\n      }\n    }\n    var child = scope.$$childHead;\n    while(child) {\n      log.push(serializeScope(child, offset + '  '));\n      child = child.$$nextSibling;\n    }\n    log.push('}');\n    return log.join('\\n' + offset);\n  }\n};\n\n/**\n * @ngdoc object\n * @name ngMock.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for unit testing application that use the\n * {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less\n * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.\n *\n * During unit testing, we want our unit tests to run quickly and have no external dependencies so\n * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or\n * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is\n * to verify whether a certain request has been sent or not, or alternatively just let the\n * application make requests, respond with pre-trained responses and assert that the end result is\n * what we expect it to be.\n *\n * This mock implementation can be used to respond with static or dynamic responses via the\n * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).\n *\n * When an Angular application needs some data from a server, it calls the $http service, which\n * sends the request to a real server using $httpBackend service. With dependency injection, it is\n * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify\n * the requests and respond with some testing data without sending a request to real server.\n *\n * There are two ways to specify what test data should be returned as http responses by the mock\n * backend when the code under test makes http requests:\n *\n * - `$httpBackend.expect` - specifies a request expectation\n * - `$httpBackend.when` - specifies a backend definition\n *\n *\n * # Request Expectations vs Backend Definitions\n *\n * Request expectations provide a way to make assertions about requests made by the application and\n * to define responses for those requests. The test will fail if the expected requests are not made\n * or they are made in the wrong order.\n *\n * Backend definitions allow you to define a fake backend for your application which doesn't assert\n * if a particular request was made or not, it just returns a trained response if a request is made.\n * The test will pass whether or not the request gets made during testing.\n *\n *\n * <table class=\"table\">\n *   <tr><th width=\"220px\"></th><th>Request expectations</th><th>Backend definitions</th></tr>\n *   <tr>\n *     <th>Syntax</th>\n *     <td>.expect(...).respond(...)</td>\n *     <td>.when(...).respond(...)</td>\n *   </tr>\n *   <tr>\n *     <th>Typical usage</th>\n *     <td>strict unit tests</td>\n *     <td>loose (black-box) unit testing</td>\n *   </tr>\n *   <tr>\n *     <th>Fulfills multiple requests</th>\n *     <td>NO</td>\n *     <td>YES</td>\n *   </tr>\n *   <tr>\n *     <th>Order of requests matters</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Request required</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Response required</th>\n *     <td>optional (see below)</td>\n *     <td>YES</td>\n *   </tr>\n * </table>\n *\n * In cases where both backend definitions and request expectations are specified during unit\n * testing, the request expectations are evaluated first.\n *\n * If a request expectation has no response specified, the algorithm will search your backend\n * definitions for an appropriate response.\n *\n * If a request didn't match any expectation or if the expectation doesn't have the response\n * defined, the backend definitions are evaluated in sequential order to see if any of them match\n * the request. The response from the first matched definition is returned.\n *\n *\n * # Flushing HTTP requests\n *\n * The $httpBackend used in production, always responds to requests with responses asynchronously.\n * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are\n * hard to write, follow and maintain. At the same time the testing mock, can't respond\n * synchronously because that would change the execution of the code under test. For this reason the\n * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending\n * requests and thus preserving the async api of the backend, while allowing the test to execute\n * synchronously.\n *\n *\n * # Unit testing with mock $httpBackend\n *\n * <pre>\n   // controller\n   function MyController($scope, $http) {\n     $http.get('/auth.py').success(function(data) {\n       $scope.user = data;\n     });\n\n     this.saveMessage = function(message) {\n       $scope.status = 'Saving...';\n       $http.post('/add-msg.py', message).success(function(response) {\n         $scope.status = '';\n       }).error(function() {\n         $scope.status = 'ERROR!';\n       });\n     };\n   }\n\n   // testing controller\n   var $httpBackend;\n\n   beforeEach(inject(function($injector) {\n     $httpBackend = $injector.get('$httpBackend');\n\n     // backend definition common for all tests\n     $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});\n   }));\n\n\n   afterEach(function() {\n     $httpBackend.verifyNoOutstandingExpectation();\n     $httpBackend.verifyNoOutstandingRequest();\n   });\n\n\n   it('should fetch authentication token', function() {\n     $httpBackend.expectGET('/auth.py');\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n   });\n\n\n   it('should send msg to server', function() {\n     // now you don’t care about the authentication, but\n     // the controller will still send the request and\n     // $httpBackend will respond without you having to\n     // specify the expectation and response for this request\n     $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');\n\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n     controller.saveMessage('message content');\n     expect(controller.status).toBe('Saving...');\n     $httpBackend.flush();\n     expect(controller.status).toBe('');\n   });\n\n\n   it('should send auth header', function() {\n     $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {\n       // check if the header was send, if it wasn't the expectation won't\n       // match the request and the test will fail\n       return headers['Authorization'] == 'xxx';\n     }).respond(201, '');\n\n     var controller = scope.$new(MyController);\n     controller.saveMessage('whatever');\n     $httpBackend.flush();\n   });\n   </pre>\n */\nangular.mock.$HttpBackendProvider = function() {\n  this.$get = [createHttpBackendMock];\n};\n\n/**\n * General factory function for $httpBackend mock.\n * Returns instance for unit testing (when no arguments specified):\n *   - passing through is disabled\n *   - auto flushing is disabled\n *\n * Returns instance for e2e testing (when `$delegate` and `$browser` specified):\n *   - passing through (delegating request to real backend) is enabled\n *   - auto flushing is enabled\n *\n * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)\n * @param {Object=} $browser Auto-flushing enabled if specified\n * @return {Object} Instance of $httpBackend mock\n */\nfunction createHttpBackendMock($delegate, $browser) {\n  var definitions = [],\n      expectations = [],\n      responses = [],\n      responsesPush = angular.bind(responses, responses.push);\n\n  function createResponse(status, data, headers) {\n    if (angular.isFunction(status)) return status;\n\n    return function() {\n      return angular.isNumber(status)\n          ? [status, data, headers]\n          : [200, status, data];\n    };\n  }\n\n  // TODO(vojta): change params to: method, url, data, headers, callback\n  function $httpBackend(method, url, data, callback, headers) {\n    var xhr = new MockXhr(),\n        expectation = expectations[0],\n        wasExpected = false;\n\n    function prettyPrint(data) {\n      return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)\n          ? data\n          : angular.toJson(data);\n    }\n\n    if (expectation && expectation.match(method, url)) {\n      if (!expectation.matchData(data))\n        throw Error('Expected ' + expectation + ' with different data\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.data) + '\\nGOT:      ' + data);\n\n      if (!expectation.matchHeaders(headers))\n        throw Error('Expected ' + expectation + ' with different headers\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.headers) + '\\nGOT:      ' +\n            prettyPrint(headers));\n\n      expectations.shift();\n\n      if (expectation.response) {\n        responses.push(function() {\n          var response = expectation.response(method, url, data, headers);\n          xhr.$$respHeaders = response[2];\n          callback(response[0], response[1], xhr.getAllResponseHeaders());\n        });\n        return;\n      }\n      wasExpected = true;\n    }\n\n    var i = -1, definition;\n    while ((definition = definitions[++i])) {\n      if (definition.match(method, url, data, headers || {})) {\n        if (definition.response) {\n          // if $browser specified, we do auto flush all requests\n          ($browser ? $browser.defer : responsesPush)(function() {\n            var response = definition.response(method, url, data, headers);\n            xhr.$$respHeaders = response[2];\n            callback(response[0], response[1], xhr.getAllResponseHeaders());\n          });\n        } else if (definition.passThrough) {\n          $delegate(method, url, data, callback, headers);\n        } else throw Error('No response defined !');\n        return;\n      }\n    }\n    throw wasExpected ?\n        Error('No response defined !') :\n        Error('Unexpected request: ' + method + ' ' + url + '\\n' +\n              (expectation ? 'Expected ' + expectation : 'No more request expected'));\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#when\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current definition.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.when = function(method, url, data, headers) {\n    var definition = new MockHttpExpectation(method, url, data, headers),\n        chain = {\n          respond: function(status, data, headers) {\n            definition.response = createResponse(status, data, headers);\n          }\n        };\n\n    if ($browser) {\n      chain.passThrough = function() {\n        definition.passThrough = true;\n      };\n    }\n\n    definitions.push(definition);\n    return chain;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for GET requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for HEAD requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for DELETE requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for POST requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for PUT requests.  For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for JSONP requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n  createShortMethods('when');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expect\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current expectation.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *  request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.expect = function(method, url, data, headers) {\n    var expectation = new MockHttpExpectation(method, url, data, headers);\n    expectations.push(expectation);\n    return {\n      respond: function(status, data, headers) {\n        expectation.response = createResponse(status, data, headers);\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for GET requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled. See #expect for more info.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for HEAD requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for DELETE requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for POST requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PUT requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPATCH\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PATCH requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for JSONP requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n  createShortMethods('expect');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#flush\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Flushes all pending requests using the trained responses.\n   *\n   * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,\n   *   all pending requests will be flushed. If there are no pending requests when the flush method\n   *   is called an exception is thrown (as this typically a sign of programming error).\n   */\n  $httpBackend.flush = function(count) {\n    if (!responses.length) throw Error('No pending request to flush !');\n\n    if (angular.isDefined(count)) {\n      while (count--) {\n        if (!responses.length) throw Error('No more pending request to flush !');\n        responses.shift()();\n      }\n    } else {\n      while (responses.length) {\n        responses.shift()();\n      }\n    }\n    $httpBackend.verifyNoOutstandingExpectation();\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingExpectation\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that all of the requests defined via the `expect` api were made. If any of the\n   * requests were not made, verifyNoOutstandingExpectation throws an exception.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyExpectations);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingExpectation = function() {\n    if (expectations.length) {\n      throw Error('Unsatisfied requests: ' + expectations.join(', '));\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingRequest\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that there are no outstanding requests that need to be flushed.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyNoOutstandingRequest);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingRequest = function() {\n    if (responses.length) {\n      throw Error('Unflushed requests: ' + responses.length);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#resetExpectations\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Resets all request expectations, but preserves all backend definitions. Typically, you would\n   * call resetExpectations during a multiple-phase test when you want to reuse the same instance of\n   * $httpBackend mock.\n   */\n  $httpBackend.resetExpectations = function() {\n    expectations.length = 0;\n    responses.length = 0;\n  };\n\n  return $httpBackend;\n\n\n  function createShortMethods(prefix) {\n    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {\n     $httpBackend[prefix + method] = function(url, headers) {\n       return $httpBackend[prefix](method, url, undefined, headers)\n     }\n    });\n\n    angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {\n      $httpBackend[prefix + method] = function(url, data, headers) {\n        return $httpBackend[prefix](method, url, data, headers)\n      }\n    });\n  }\n}\n\nfunction MockHttpExpectation(method, url, data, headers) {\n\n  this.data = data;\n  this.headers = headers;\n\n  this.match = function(m, u, d, h) {\n    if (method != m) return false;\n    if (!this.matchUrl(u)) return false;\n    if (angular.isDefined(d) && !this.matchData(d)) return false;\n    if (angular.isDefined(h) && !this.matchHeaders(h)) return false;\n    return true;\n  };\n\n  this.matchUrl = function(u) {\n    if (!url) return true;\n    if (angular.isFunction(url.test)) return url.test(u);\n    return url == u;\n  };\n\n  this.matchHeaders = function(h) {\n    if (angular.isUndefined(headers)) return true;\n    if (angular.isFunction(headers)) return headers(h);\n    return angular.equals(headers, h);\n  };\n\n  this.matchData = function(d) {\n    if (angular.isUndefined(data)) return true;\n    if (data && angular.isFunction(data.test)) return data.test(d);\n    if (data && !angular.isString(data)) return angular.toJson(data) == d;\n    return data == d;\n  };\n\n  this.toString = function() {\n    return method + ' ' + url;\n  };\n}\n\nfunction MockXhr() {\n\n  // hack for testing $http, $httpBackend\n  MockXhr.$$lastInstance = this;\n\n  this.open = function(method, url, async) {\n    this.$$method = method;\n    this.$$url = url;\n    this.$$async = async;\n    this.$$reqHeaders = {};\n    this.$$respHeaders = {};\n  };\n\n  this.send = function(data) {\n    this.$$data = data;\n  };\n\n  this.setRequestHeader = function(key, value) {\n    this.$$reqHeaders[key] = value;\n  };\n\n  this.getResponseHeader = function(name) {\n    // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last\n    var header = this.$$respHeaders[name];\n    if (header) return header;\n\n    name = angular.lowercase(name);\n    header = this.$$respHeaders[name];\n    if (header) return header;\n\n    header = undefined;\n    angular.forEach(this.$$respHeaders, function(headerVal, headerName) {\n      if (!header && angular.lowercase(headerName) == name) header = headerVal;\n    });\n    return header;\n  };\n\n  this.getAllResponseHeaders = function() {\n    var lines = [];\n\n    angular.forEach(this.$$respHeaders, function(value, key) {\n      lines.push(key + ': ' + value);\n    });\n    return lines.join('\\n');\n  };\n\n  this.abort = angular.noop;\n}\n\n\n/**\n * @ngdoc function\n * @name ngMock.$timeout\n * @description\n *\n * This service is just a simple decorator for {@link ng.$timeout $timeout} service\n * that adds a \"flush\" method.\n */\n\n/**\n * @ngdoc method\n * @name ngMock.$timeout#flush\n * @methodOf ngMock.$timeout\n * @description\n *\n * Flushes the queue of pending tasks.\n */\n\n/**\n *\n */\nangular.mock.$RootElementProvider = function() {\n  this.$get = function() {\n    return angular.element('<div ng-app></div>');\n  }\n};\n\n/**\n * @ngdoc overview\n * @name ngMock\n * @description\n *\n * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful\n * mocks to the {@link AUTO.$injector $injector}.\n */\nangular.module('ngMock', ['ng']).provider({\n  $browser: angular.mock.$BrowserProvider,\n  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,\n  $log: angular.mock.$LogProvider,\n  $httpBackend: angular.mock.$HttpBackendProvider,\n  $rootElement: angular.mock.$RootElementProvider\n}).config(function($provide) {\n  $provide.decorator('$timeout', function($delegate, $browser) {\n    $delegate.flush = function() {\n      $browser.defer.flush();\n    };\n    return $delegate;\n  });\n});\n\n\n/**\n * @ngdoc overview\n * @name ngMockE2E\n * @description\n *\n * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.\n * Currently there is only one mock present in this module -\n * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.\n */\nangular.module('ngMockE2E', ['ng']).config(function($provide) {\n  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);\n});\n\n/**\n * @ngdoc object\n * @name ngMockE2E.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of\n * applications that use the {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for unit testing please see\n * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.\n *\n * This implementation can be used to respond with static or dynamic responses via the `when` api\n * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the\n * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch\n * templates from a webserver).\n *\n * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application\n * is being developed with the real backend api replaced with a mock, it is often desirable for\n * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch\n * templates or static files from the webserver). To configure the backend with this behavior\n * use the `passThrough` request handler of `when` instead of `respond`.\n *\n * Additionally, we don't want to manually have to flush mocked out requests like we do during unit\n * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests\n * automatically, closely simulating the behavior of the XMLHttpRequest object.\n *\n * To setup the application to run with this http backend, you have to create a module that depends\n * on the `ngMockE2E` and your application modules and defines the fake backend:\n *\n * <pre>\n *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);\n *   myAppDev.run(function($httpBackend) {\n *     phones = [{name: 'phone1'}, {name: 'phone2'}];\n *\n *     // returns the current list of phones\n *     $httpBackend.whenGET('/phones').respond(phones);\n *\n *     // adds a new phone to the phones array\n *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {\n *       phones.push(angular.fromJSON(data));\n *     });\n *     $httpBackend.whenGET(/^\\/templates\\//).passThrough();\n *     //...\n *   });\n * </pre>\n *\n * Afterwards, bootstrap your app with this new module.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#when\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition.\n *\n * @param {string} method HTTP method.\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n *   object and returns true if the headers match the current definition.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n *\n *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n *    – The respond method takes a set of static data to be returned or a function that can return\n *    an array containing response status (number), response data (string) and response headers\n *    (Object).\n *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`\n *    handler, will be pass through to the real backend (an XHR request will be made to the\n *    server.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenGET\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for GET requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenHEAD\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for HEAD requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenDELETE\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for DELETE requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPOST\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for POST requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPUT\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PUT requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPATCH\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PATCH requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenJSONP\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for JSONP requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\nangular.mock.e2e = {};\nangular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];\n\n\nangular.mock.clearDataCache = function() {\n  var key,\n      cache = angular.element.cache;\n\n  for(key in cache) {\n    if (cache.hasOwnProperty(key)) {\n      var handle = cache[key].handle;\n\n      handle && angular.element(handle.elem).unbind();\n      delete cache[key];\n    }\n  }\n};\n\n\nwindow.jstestdriver && (function(window) {\n  /**\n   * Global method to output any number of objects into JSTD console. Useful for debugging.\n   */\n  window.dump = function() {\n    var args = [];\n    angular.forEach(arguments, function(arg) {\n      args.push(angular.mock.dump(arg));\n    });\n    jstestdriver.console.log.apply(jstestdriver.console, args);\n    if (window.console) {\n      window.console.log.apply(window.console, args);\n    }\n  };\n})(window);\n\n\nwindow.jasmine && (function(window) {\n\n  afterEach(function() {\n    var spec = getCurrentSpec();\n    var injector = spec.$injector;\n\n    spec.$injector = null;\n    spec.$modules = null;\n\n    if (injector) {\n      injector.get('$rootElement').unbind();\n      injector.get('$browser').pollFns.length = 0;\n    }\n\n    angular.mock.clearDataCache();\n\n    // clean up jquery's fragment cache\n    angular.forEach(angular.element.fragments, function(val, key) {\n      delete angular.element.fragments[key];\n    });\n\n    MockXhr.$$lastInstance = null;\n\n    angular.forEach(angular.callbacks, function(val, key) {\n      delete angular.callbacks[key];\n    });\n    angular.callbacks.counter = 0;\n  });\n\n  function getCurrentSpec() {\n    return jasmine.getEnv().currentSpec;\n  }\n\n  function isSpecRunning() {\n    var spec = getCurrentSpec();\n    return spec && spec.queue.running;\n  }\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.module\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * This function registers a module configuration code. It collects the configuration information\n   * which will be used when the injector is created by {@link angular.mock.inject inject}.\n   *\n   * See {@link angular.mock.inject inject} for usage example\n   *\n   * @param {...(string|Function)} fns any number of modules which are represented as string\n   *        aliases or as anonymous module initialization functions. The modules are used to\n   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.\n   */\n  window.module = angular.mock.module = function() {\n    var moduleFns = Array.prototype.slice.call(arguments, 0);\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      if (spec.$injector) {\n        throw Error('Injector already created, can not register a module!');\n      } else {\n        var modules = spec.$modules || (spec.$modules = []);\n        angular.forEach(moduleFns, function(module) {\n          modules.push(module);\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.inject\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * The inject function wraps a function into an injectable function. The inject() creates new\n   * instance of {@link AUTO.$injector $injector} per test, which is then used for\n   * resolving references.\n   *\n   * See also {@link angular.mock.module module}\n   *\n   * Example of what a typical jasmine tests looks like with the inject method.\n   * <pre>\n   *\n   *   angular.module('myApplicationModule', [])\n   *       .value('mode', 'app')\n   *       .value('version', 'v1.0.1');\n   *\n   *\n   *   describe('MyApp', function() {\n   *\n   *     // You need to load modules that you want to test,\n   *     // it loads only the \"ng\" module by default.\n   *     beforeEach(module('myApplicationModule'));\n   *\n   *\n   *     // inject() is used to inject arguments of all given functions\n   *     it('should provide a version', inject(function(mode, version) {\n   *       expect(version).toEqual('v1.0.1');\n   *       expect(mode).toEqual('app');\n   *     }));\n   *\n   *\n   *     // The inject and module method can also be used inside of the it or beforeEach\n   *     it('should override a version and test the new version is injected', function() {\n   *       // module() takes functions or strings (module aliases)\n   *       module(function($provide) {\n   *         $provide.value('version', 'overridden'); // override version here\n   *       });\n   *\n   *       inject(function(version) {\n   *         expect(version).toEqual('overridden');\n   *       });\n   *     ));\n   *   });\n   *\n   * </pre>\n   *\n   * @param {...Function} fns any number of functions which will be injected using the injector.\n   */\n  window.inject = angular.mock.inject = function() {\n    var blockFns = Array.prototype.slice.call(arguments, 0);\n    var errorForStack = new Error('Declaration Location');\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      var modules = spec.$modules || [];\n      modules.unshift('ngMock');\n      modules.unshift('ng');\n      var injector = spec.$injector;\n      if (!injector) {\n        injector = spec.$injector = angular.injector(modules);\n      }\n      for(var i = 0, ii = blockFns.length; i < ii; i++) {\n        try {\n          injector.invoke(blockFns[i] || angular.noop, this);\n        } catch (e) {\n          if(e.stack) e.stack +=  '\\n' + errorForStack.stack;\n          throw e;\n        } finally {\n          errorForStack = null;\n        }\n      }\n    }\n  };\n})(window);\n"
  },
  {
    "path": "chapter6/recipe1/test/lib/angular/angular-scenario.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Mar 21 12:46:34 2012 -0700\n */\n(function( window, undefined ) {\n'use strict';\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.7.2\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in array && array[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n\t\tvar exec,\n\t\t\tbulk = key == null,\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\n\t\t// Sets many values\n\t\tif ( key && typeof key === \"object\" ) {\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n\t\t\t}\n\t\t\tchainable = 1;\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = pass === undefined && jQuery.isFunction( value );\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations only iterate when executing function values\n\t\t\t\tif ( exec ) {\n\t\t\t\t\texec = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn exec.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\n\t\t\t\t// Otherwise they run against the entire set\n\t\t\t\t} else {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor (; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchainable = 1;\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfired = true;\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar length = list.length;\n\t\t\t\t\tadd( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory || memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tfragment,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tpixelMargin: true\n\t};\n\n\t// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead\n\tjQuery.boxModel = support.boxModel = (document.compatMode === \"CSS1Compat\");\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor ( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\tfragment.removeChild( div );\n\n\t// Null elements to avoid leaks in IE\n\tfragment = select = opt = div = input = null;\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tmarginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,\n\t\t\tpaddingMarginBorderVisibility, paddingMarginBorder,\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tconMarginTop = 1;\n\t\tpaddingMarginBorder = \"padding:0;margin:0;border:\";\n\t\tpositionTopLeftWidthHeight = \"position:absolute;top:0;left:0;width:1px;height:1px;\";\n\t\tpaddingMarginBorderVisibility = paddingMarginBorder + \"0;visibility:hidden;\";\n\t\tstyle = \"style='\" + positionTopLeftWidthHeight + paddingMarginBorder + \"5px solid #000;\";\n\t\thtml = \"<div \" + style + \"display:block;'><div style='\" + paddingMarginBorder + \"0;display:block;overflow:hidden;'></div></div>\" +\n\t\t\t\"<table \" + style + \"' cellpadding='0' cellspacing='0'>\" +\n\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = paddingMarginBorderVisibility + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td style='\" + paddingMarginBorder + \"0;display:none'></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName( \"td\" );\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t// gets computed margin-right based on width of container. For more\n\t\t// info see bug #3333\n\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tmarginDiv = document.createElement( \"div\" );\n\t\t\tmarginDiv.style.width = \"0\";\n\t\t\tmarginDiv.style.marginRight = \"0\";\n\t\t\tdiv.style.width = \"2px\";\n\t\t\tdiv.appendChild( marginDiv );\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\t// (IE < 8 does this)\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.width = div.style.padding = \"1px\";\n\t\t\tdiv.style.border = 0;\n\t\t\tdiv.style.overflow = \"hidden\";\n\t\t\tdiv.style.display = \"inline\";\n\t\t\tdiv.style.zoom = 1;\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.style.overflow = \"visible\";\n\t\t\tdiv.innerHTML = \"<div style='width:5px;'></div>\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\t\t}\n\n\t\tdiv.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;\n\t\tdiv.innerHTML = html;\n\n\t\touter = div.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.style.marginTop = \"1%\";\n\t\t\tsupport.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== \"1%\";\n\t\t}\n\n\t\tif ( typeof container.style.zoom !== \"undefined\" ) {\n\t\t\tcontainer.style.zoom = 1;\n\t\t}\n\n\t\tbody.removeChild( container );\n\t\tmarginDiv = div = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\treturn support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ internalKey ] : internalKey;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ internalKey ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( internalKey );\n\t\t\t} else {\n\t\t\t\telem[ internalKey ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, part, attr, name, l,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = elem.attributes;\n\t\t\t\t\tfor ( l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split( \".\", 2 );\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\t\tpart = parts[1] + \"!\";\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\tdata = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\tif ( data === undefined && elem ) {\n\t\t\t\t\tdata = jQuery.data( elem, key );\n\t\t\t\t\tdata = dataAttr( elem, key, data );\n\t\t\t\t}\n\n\t\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\t\tdata;\n\t\t\t}\n\n\t\t\tparts[1] = value;\n\t\t\tthis.each(function() {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.triggerHandler( \"setData\" + part, parts );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + part, parts );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, false );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\thooks = {};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( object );\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, l, isBool,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\t\t\tattrNames = value.toLowerCase().split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tisBool = rboolean.test( name );\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\t// Do not do this for boolean attributes (see #10870)\n\t\t\t\t\tif ( !isBool ) {\n\t\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\t}\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( isBool && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true,\n\t\tcoords: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = \"\" + value );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+)?\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\tvar attrs = elem.attributes || {};\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || (attrs.id || {}).value === m[2]) &&\n\t\t\t(!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tquick: selector && quickParse( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t ( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\told = null;\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\tspecial = jQuery.event.special[ event.type ] || {},\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n\t\t\t// Pregenerate a single jQuery object for reuse with .is()\n\t\t\tjqcur = jQuery(this);\n\t\t\tjqcur.context = this.ownerDocument || this;\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process events on disabled elements (#6911, #8165)\n\t\t\t\tif ( cur.disabled !== true ) {\n\t\t\t\t\tselMatch = {};\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tjqcur[0] = cur;\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\t\tselMatch[ sel ] = (\n\t\t\t\t\t\t\t\thandleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\tret;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\t\t\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\telem._change_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) { // && selector != null\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( var type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\n\t\t\tparts.push( m[1] );\n\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\t\t/* falls through */\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n// Expose origPOS\n// \"global\" as in regardless of relation to brackets/parens\nExpr.match.globalPOS = origPOS;\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry {\n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.globalPOS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\tPOS.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery.clean(arguments) );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tnull;\n\t\t\t}\n\n\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, function( i, elem ) {\n\t\t\t\t\tif ( elem.src ) {\n\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\turl: elem.src,\n\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\tdataType: \"script\"\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\n\t// IE blanks contents when cloning scripts\n\t} else if ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdest.text = src.text;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n\n\t// Clear flags for bubbling special change/submit events, they must\n\t// be reattached when the newly cloned events are first activated\n\tdest.removeAttribute( \"_submit_attached\" );\n\tdest.removeAttribute( \"_change_attached\" );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n\t// Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n\tvar div = document.createElement( \"div\" );\n\tsafeFragment.appendChild( div );\n\n\tdiv.innerHTML = elem.outerHTML;\n\treturn div.firstChild;\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t\tclone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ?\n\t\t\t\telem.cloneNode( true ) :\n\t\t\t\tshimCloneNode( elem );\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType, script, j,\n\t\t\t\tret = [];\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\"),\n\t\t\t\t\t\tsafeChildNodes = safeFragment.childNodes,\n\t\t\t\t\t\tremove;\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\n\t\t\t\t\t// Clear elements from DocumentFragment (safeFragment or otherwise)\n\t\t\t\t\t// to avoid hoarding elements. Fixes #11356\n\t\t\t\t\tif ( div ) {\n\t\t\t\t\t\tdiv.parentNode.removeChild( div );\n\n\t\t\t\t\t\t// Guard against -1 index exceptions in FF3.6\n\t\t\t\t\t\tif ( safeChildNodes.length > 0 ) {\n\t\t\t\t\t\t\tremove = safeChildNodes[ safeChildNodes.length - 1 ];\n\n\t\t\t\t\t\t\tif ( remove && remove.parentNode ) {\n\t\t\t\t\t\t\t\tremove.parentNode.removeChild( remove );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tscript = ret[i];\n\t\t\t\tif ( scripts && jQuery.nodeName( script, \"script\" ) && (!script.type || rscriptType.test( script.type )) ) {\n\t\t\t\t\tscripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( script.nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( script.getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( script );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnum = /^[\\-+]?(?:\\d*\\.)?\\d+$/i,\n\trnumnonpx = /^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\trmargin = /^margin/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\n\t// order is important!\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\treturn jQuery.access( this, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t}, name, value, arguments.length > 1 );\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {},\n\t\t\tret, name;\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// DEPRECATED in 1.3, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle, width,\n\t\t\tstyle = elem.style;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( (defaultView = elem.ownerDocument.defaultView) &&\n\t\t\t\t(computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// WebKit uses \"computed value (percentage if specified)\" instead of \"used value\" for margins\n\t\t// which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {\n\t\t\twidth = style.width;\n\t\t\tstyle.width = ret;\n\t\t\tret = computedStyle.width;\n\t\t\tstyle.width = width;\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( rnumnonpx.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\ti = name === \"width\" ? 1 : 0,\n\t\tlen = 4;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tfor ( ; i < len; i += 2 ) {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ];\n\t}\n\n\t// Computed unit is not pixels. Stop here and return.\n\tif ( rnumnonpx.test(val) ) {\n\t\treturn val;\n\t}\n\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tfor ( ; i < len; i += 2 ) {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val + \"px\";\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\treturn jQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\treturn rnum.test( value ) ?\n\t\t\t\tvalue + \"px\" :\n\t\t\t\tvalue;\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\treturn curCSS( elem, \"margin-right\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i,\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n\t\t\t\texpanded = {};\n\n\t\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n});\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = ( typeof s.data === \"string\" ) && /^application\\/x\\-www\\-form\\-urlencoded/.test( s.contentType );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t} catch( _ ) {\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( (display === \"\" && jQuery.css(elem, \"display\") === \"none\") ||\n\t\t\t\t\t\t!jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e, hooks, replace,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\t// first pass over propertys to expand / normalize\n\t\t\tfor ( p in prop ) {\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tif ( ( hooks = jQuery.cssHooks[ name ] ) && \"expand\" in hooks ) {\n\t\t\t\t\treplace = hooks.expand( prop[ name ] );\n\t\t\t\t\tdelete prop[ name ];\n\n\t\t\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t\t\t// also - reusing 'p' from above because we have the correct \"name\"\n\t\t\t\t\tfor ( p in replace ) {\n\t\t\t\t\t\tif ( ! ( p in prop ) ) {\n\t\t\t\t\t\t\tprop[ p ] = replace[ p ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( name in prop ) {\n\t\t\t\tval = prop[ name ];\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, index ) {\n\t\t\t\tvar hooks = data[ index ];\n\t\t\t\tjQuery.removeData( elem, index, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n\t\t\t\tstopQueue( this, data, index );\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ index ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ index ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p ) {\n\t\t\treturn p;\n\t\t},\n\t\tswing: function( p ) {\n\t\t\treturn ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tif ( self.options.hide ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t\t} else if ( self.options.show ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.end );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Ensure props that can't be negative don't go there on undershoot easing\njQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {\n\t// exclude marginTop, marginLeft, marginBottom and marginRight from this list\n\tif ( prop.indexOf( \"margin\" ) ) {\n\t\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( jQuery.support.boxModel ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar getOffset,\n\trtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tgetOffset = function( elem, doc, docElem, box ) {\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow( doc ),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tgetOffset = function( elem, doc, docElem ) {\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar elem = this[0],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn null;\n\t}\n\n\tif ( elem === doc.body ) {\n\t\treturn jQuery.offset.bodyOffset( elem );\n\t}\n\n\treturn getOffset( elem, doc, doc.documentElement );\n};\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t top ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tvar clientProp = \"client\" + name,\n\t\tscrollProp = \"scroll\" + name,\n\t\toffsetProp = \"offset\" + name;\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( value ) {\n\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\tvar doc, docElemProp, orig, ret;\n\n\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\t\tdoc = elem.document;\n\t\t\t\tdocElemProp = doc.documentElement[ clientProp ];\n\t\t\t\treturn jQuery.support.boxModel && docElemProp ||\n\t\t\t\t\tdoc.body && doc.body[ clientProp ] || docElemProp;\n\t\t\t}\n\n\t\t\t// Get document width or height\n\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t// when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]\n\t\t\t\t// so we can't use max, as it'll choose the incorrect offset[Width/Height]\n\t\t\t\t// instead we use the correct client[Width/Height]\n\t\t\t\t// support:IE6\n\t\t\t\tif ( doc[ clientProp ] >= doc[ scrollProp ] ) {\n\t\t\t\t\treturn doc[ clientProp ];\n\t\t\t\t}\n\n\t\t\t\treturn Math.max(\n\t\t\t\t\telem.body[ scrollProp ], doc[ scrollProp ],\n\t\t\t\t\telem.body[ offsetProp ], doc[ offsetProp ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get width or height on the element\n\t\t\tif ( value === undefined ) {\n\t\t\t\torig = jQuery.css( elem, type );\n\t\t\t\tret = parseFloat( orig );\n\t\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\t\t\t}\n\n\t\t\t// Set the width or height on the element\n\t\t\tjQuery( elem ).css( type, value );\n\t\t}, type, value, arguments.length, null );\n\t};\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );\n/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document){\n  var _jQuery = window.jQuery.noConflict(true);\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n\n/**\n * Setup file for the Scenario.\n * Must be first in the compilation/bootstrap list.\n */\n\n// Public namespace\nangular.scenario = angular.scenario || {};\n\n/**\n * Defines a new output format.\n *\n * @param {string} name the name of the new output format\n * @param {function()} fn function(context, runner) that generates the output\n */\nangular.scenario.output = angular.scenario.output || function(name, fn) {\n  angular.scenario.output[name] = fn;\n};\n\n/**\n * Defines a new DSL statement. If your factory function returns a Future\n * it's returned, otherwise the result is assumed to be a map of functions\n * for chaining. Chained functions are subject to the same rules.\n *\n * Note: All functions on the chain are bound to the chain scope so values\n *   set on \"this\" in your statement function are available in the chained\n *   functions.\n *\n * @param {string} name The name of the statement\n * @param {function()} fn Factory function(), return a function for\n *  the statement.\n */\nangular.scenario.dsl = angular.scenario.dsl || function(name, fn) {\n  angular.scenario.dsl[name] = function() {\n    function executeStatement(statement, args) {\n      var result = statement.apply(this, args);\n      if (angular.isFunction(result) || result instanceof angular.scenario.Future)\n        return result;\n      var self = this;\n      var chain = angular.extend({}, result);\n      angular.forEach(chain, function(value, name) {\n        if (angular.isFunction(value)) {\n          chain[name] = function() {\n            return executeStatement.call(self, value, arguments);\n          };\n        } else {\n          chain[name] = value;\n        }\n      });\n      return chain;\n    }\n    var statement = fn.apply(this, arguments);\n    return function() {\n      return executeStatement.call(this, statement, arguments);\n    };\n  };\n};\n\n/**\n * Defines a new matcher for use with the expects() statement. The value\n * this.actual (like in Jasmine) is available in your matcher to compare\n * against. Your function should return a boolean. The future is automatically\n * created for you.\n *\n * @param {string} name The name of the matcher\n * @param {function()} fn The matching function(expected).\n */\nangular.scenario.matcher = angular.scenario.matcher || function(name, fn) {\n  angular.scenario.matcher[name] = function(expected) {\n    var prefix = 'expect ' + this.future.name + ' ';\n    if (this.inverse) {\n      prefix += 'not ';\n    }\n    var self = this;\n    this.addFuture(prefix + name + ' ' + angular.toJson(expected),\n      function(done) {\n        var error;\n        self.actual = self.future.value;\n        if ((self.inverse && fn.call(self, expected)) ||\n            (!self.inverse && !fn.call(self, expected))) {\n          error = 'expected ' + angular.toJson(expected) +\n            ' but was ' + angular.toJson(self.actual);\n        }\n        done(error);\n    });\n  };\n};\n\n/**\n * Initialize the scenario runner and run !\n *\n * Access global window and document object\n * Access $runner through closure\n *\n * @param {Object=} config Config options\n */\nangular.scenario.setUpAndRun = function(config) {\n  var href = window.location.href;\n  var body = _jQuery(document.body);\n  var output = [];\n  var objModel = new angular.scenario.ObjectModel($runner);\n\n  if (config && config.scenario_output) {\n    output = config.scenario_output.split(',');\n  }\n\n  angular.forEach(angular.scenario.output, function(fn, name) {\n    if (!output.length || indexOf(output,name) != -1) {\n      var context = body.append('<div></div>').find('div:last');\n      context.attr('id', name);\n      fn.call({}, context, $runner, objModel);\n    }\n  });\n\n  if (!/^http/.test(href) && !/^https/.test(href)) {\n    body.append('<p id=\"system-error\"></p>');\n    body.find('#system-error').text(\n      'Scenario runner must be run using http or https. The protocol ' +\n      href.split(':')[0] + ':// is not supported.'\n    );\n    return;\n  }\n\n  var appFrame = body.append('<div id=\"application\"></div>').find('#application');\n  var application = new angular.scenario.Application(appFrame);\n\n  $runner.on('RunnerEnd', function() {\n    appFrame.css('display', 'none');\n    appFrame.find('iframe').attr('src', 'about:blank');\n  });\n\n  $runner.on('RunnerError', function(error) {\n    if (window.console) {\n      console.log(formatException(error));\n    } else {\n      // Do something for IE\n      alert(error);\n    }\n  });\n\n  $runner.run(application);\n};\n\n/**\n * Iterates through list with iterator function that must call the\n * continueFunction to continute iterating.\n *\n * @param {Array} list list to iterate over\n * @param {function()} iterator Callback function(value, continueFunction)\n * @param {function()} done Callback function(error, result) called when\n *   iteration finishes or an error occurs.\n */\nfunction asyncForEach(list, iterator, done) {\n  var i = 0;\n  function loop(error, index) {\n    if (index && index > i) {\n      i = index;\n    }\n    if (error || i >= list.length) {\n      done(error);\n    } else {\n      try {\n        iterator(list[i++], loop);\n      } catch (e) {\n        done(e);\n      }\n    }\n  }\n  loop();\n}\n\n/**\n * Formats an exception into a string with the stack trace, but limits\n * to a specific line length.\n *\n * @param {Object} error The exception to format, can be anything throwable\n * @param {Number=} [maxStackLines=5] max lines of the stack trace to include\n *  default is 5.\n */\nfunction formatException(error, maxStackLines) {\n  maxStackLines = maxStackLines || 5;\n  var message = error.toString();\n  if (error.stack) {\n    var stack = error.stack.split('\\n');\n    if (stack[0].indexOf(message) === -1) {\n      maxStackLines++;\n      stack.unshift(error.message);\n    }\n    message = stack.slice(0, maxStackLines).join('\\n');\n  }\n  return message;\n}\n\n/**\n * Returns a function that gets the file name and line number from a\n * location in the stack if available based on the call site.\n *\n * Note: this returns another function because accessing .stack is very\n * expensive in Chrome.\n *\n * @param {Number} offset Number of stack lines to skip\n */\nfunction callerFile(offset) {\n  var error = new Error();\n\n  return function() {\n    var line = (error.stack || '').split('\\n')[offset];\n\n    // Clean up the stack trace line\n    if (line) {\n      if (line.indexOf('@') !== -1) {\n        // Firefox\n        line = line.substring(line.indexOf('@')+1);\n      } else {\n        // Chrome\n        line = line.substring(line.indexOf('(')+1).replace(')', '');\n      }\n    }\n\n    return line || '';\n  };\n}\n\n/**\n * Triggers a browser event. Attempts to choose the right event if one is\n * not specified.\n *\n * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement\n * @param {string} type Optional event type.\n * @param {Array.<string>=} keys Optional list of pressed keys\n *        (valid values: 'alt', 'meta', 'shift', 'ctrl')\n */\nfunction browserTrigger(element, type, keys) {\n  if (element && !element.nodeName) element = element[0];\n  if (!element) return;\n  if (!type) {\n    type = {\n        'text':            'change',\n        'textarea':        'change',\n        'hidden':          'change',\n        'password':        'change',\n        'button':          'click',\n        'submit':          'click',\n        'reset':           'click',\n        'image':           'click',\n        'checkbox':        'click',\n        'radio':           'click',\n        'select-one':      'change',\n        'select-multiple': 'change'\n    }[lowercase(element.type)] || 'click';\n  }\n  if (lowercase(nodeName_(element)) == 'option') {\n    element.parentNode.value = element.value;\n    element = element.parentNode;\n    type = 'change';\n  }\n\n  keys = keys || [];\n  function pressed(key) {\n    return indexOf(keys, key) !== -1;\n  }\n\n  if (msie < 9) {\n    switch(element.type) {\n      case 'radio':\n      case 'checkbox':\n        element.checked = !element.checked;\n        break;\n    }\n    // WTF!!! Error: Unspecified error.\n    // Don't know why, but some elements when detached seem to be in inconsistent state and\n    // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)\n    // forcing the browser to compute the element position (by reading its CSS)\n    // puts the element in consistent state.\n    element.style.posLeft;\n\n    // TODO(vojta): create event objects with pressed keys to get it working on IE<9\n    var ret = element.fireEvent('on' + type);\n    if (lowercase(element.type) == 'submit') {\n      while(element) {\n        if (lowercase(element.nodeName) == 'form') {\n          element.fireEvent('onsubmit');\n          break;\n        }\n        element = element.parentNode;\n      }\n    }\n    return ret;\n  } else {\n    var evnt = document.createEvent('MouseEvents'),\n        originalPreventDefault = evnt.preventDefault,\n        iframe = _jQuery('#application iframe')[0],\n        appWindow = iframe ? iframe.contentWindow : window,\n        fakeProcessDefault = true,\n        finalProcessDefault,\n        angular = appWindow.angular || {};\n\n    // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208\n    angular['ff-684208-preventDefault'] = false;\n    evnt.preventDefault = function() {\n      fakeProcessDefault = false;\n      return originalPreventDefault.apply(evnt, arguments);\n    };\n\n    evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, pressed('ctrl'), pressed('alt'),\n                        pressed('shift'), pressed('meta'), 0, element);\n\n    element.dispatchEvent(evnt);\n    finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);\n\n    delete angular['ff-684208-preventDefault'];\n\n    return finalProcessDefault;\n  }\n}\n\n/**\n * Don't use the jQuery trigger method since it works incorrectly.\n *\n * jQuery notifies listeners and then changes the state of a checkbox and\n * does not create a real browser event. A real click changes the state of\n * the checkbox and then notifies listeners.\n *\n * To work around this we instead use our own handler that fires a real event.\n */\n(function(fn){\n  var parentTrigger = fn.trigger;\n  fn.trigger = function(type) {\n    if (/(click|change|keydown|blur|input)/.test(type)) {\n      var processDefaults = [];\n      this.each(function(index, node) {\n        processDefaults.push(browserTrigger(node, type));\n      });\n\n      // this is not compatible with jQuery - we return an array of returned values,\n      // so that scenario runner know whether JS code has preventDefault() of the event or not...\n      return processDefaults;\n    }\n    return parentTrigger.apply(this, arguments);\n  };\n})(_jQuery.fn);\n\n/**\n * Finds all bindings with the substring match of name and returns an\n * array of their values.\n *\n * @param {string} bindExp The name to match\n * @return {Array.<string>} String of binding values\n */\n_jQuery.fn.bindings = function(windowJquery, bindExp) {\n  var result = [], match,\n      bindSelector = '.ng-binding:visible';\n  if (angular.isString(bindExp)) {\n    bindExp = bindExp.replace(/\\s/g, '');\n    match = function (actualExp) {\n      if (actualExp) {\n        actualExp = actualExp.replace(/\\s/g, '');\n        if (actualExp == bindExp) return true;\n        if (actualExp.indexOf(bindExp) == 0) {\n          return actualExp.charAt(bindExp.length) == '|';\n        }\n      }\n    }\n  } else if (bindExp) {\n    match = function(actualExp) {\n      return actualExp && bindExp.exec(actualExp);\n    }\n  } else {\n    match = function(actualExp) {\n      return !!actualExp;\n    };\n  }\n  var selection = this.find(bindSelector);\n  if (this.is(bindSelector)) {\n    selection = selection.add(this);\n  }\n\n  function push(value) {\n    if (value == undefined) {\n      value = '';\n    } else if (typeof value != 'string') {\n      value = angular.toJson(value);\n    }\n    result.push('' + value);\n  }\n\n  selection.each(function() {\n    var element = windowJquery(this),\n        binding;\n    if (binding = element.data('$binding')) {\n      if (typeof binding == 'string') {\n        if (match(binding)) {\n          push(element.scope().$eval(binding));\n        }\n      } else {\n        if (!angular.isArray(binding)) {\n          binding = [binding];\n        }\n        for(var fns, j=0, jj=binding.length;  j<jj; j++) {\n          fns = binding[j];\n          if (fns.parts) {\n            fns = fns.parts;\n          } else {\n            fns = [fns];\n          }\n          for (var scope, fn, i = 0, ii = fns.length; i < ii; i++) {\n            if(match((fn = fns[i]).exp)) {\n              push(fn(scope = scope || element.scope()));\n            }\n          }\n        }\n      }\n    }\n  });\n  return result;\n};\n\n/**\n * Represents the application currently being tested and abstracts usage\n * of iframes or separate windows.\n *\n * @param {Object} context jQuery wrapper around HTML context.\n */\nangular.scenario.Application = function(context) {\n  this.context = context;\n  context.append(\n    '<h2>Current URL: <a href=\"about:blank\">None</a></h2>' +\n    '<div id=\"test-frames\"></div>'\n  );\n};\n\n/**\n * Gets the jQuery collection of frames. Don't use this directly because\n * frames may go stale.\n *\n * @private\n * @return {Object} jQuery collection\n */\nangular.scenario.Application.prototype.getFrame_ = function() {\n  return this.context.find('#test-frames iframe:last');\n};\n\n/**\n * Gets the window of the test runner frame. Always favor executeAction()\n * instead of this method since it prevents you from getting a stale window.\n *\n * @private\n * @return {Object} the window of the frame\n */\nangular.scenario.Application.prototype.getWindow_ = function() {\n  var contentWindow = this.getFrame_().prop('contentWindow');\n  if (!contentWindow)\n    throw 'Frame window is not accessible.';\n  return contentWindow;\n};\n\n/**\n * Changes the location of the frame.\n *\n * @param {string} url The URL. If it begins with a # then only the\n *   hash of the page is changed.\n * @param {function()} loadFn function($window, $document) Called when frame loads.\n * @param {function()} errorFn function(error) Called if any error when loading.\n */\nangular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorFn) {\n  var self = this;\n  var frame = this.getFrame_();\n  //TODO(esprehn): Refactor to use rethrow()\n  errorFn = errorFn || function(e) { throw e; };\n  if (url === 'about:blank') {\n    errorFn('Sandbox Error: Navigating to about:blank is not allowed.');\n  } else if (url.charAt(0) === '#') {\n    url = frame.attr('src').split('#')[0] + url;\n    frame.attr('src', url);\n    this.executeAction(loadFn);\n  } else {\n    frame.remove();\n    this.context.find('#test-frames').append('<iframe>');\n    frame = this.getFrame_();\n    frame.load(function() {\n      frame.unbind();\n      try {\n        self.executeAction(loadFn);\n      } catch (e) {\n        errorFn(e);\n      }\n    }).attr('src', url);\n  }\n  this.context.find('> h2 a').attr('href', url).text(url);\n};\n\n/**\n * Executes a function in the context of the tested application. Will wait\n * for all pending angular xhr requests before executing.\n *\n * @param {function()} action The callback to execute. function($window, $document)\n *  $document is a jQuery wrapped document.\n */\nangular.scenario.Application.prototype.executeAction = function(action) {\n  var self = this;\n  var $window = this.getWindow_();\n  if (!$window.document) {\n    throw 'Sandbox Error: Application document not accessible.';\n  }\n  if (!$window.angular) {\n    return action.call(this, $window, _jQuery($window.document));\n  }\n  angularInit($window.document, function(element) {\n    var $injector = $window.angular.element(element).injector();\n    var $element = _jQuery(element);\n\n    $element.injector = function() {\n      return $injector;\n    };\n\n    $injector.invoke(function($browser){\n      $browser.notifyWhenNoOutstandingRequests(function() {\n        action.call(self, $window, $element);\n      });\n    });\n  });\n};\n\n/**\n * The representation of define blocks. Don't used directly, instead use\n * define() in your tests.\n *\n * @param {string} descName Name of the block\n * @param {Object} parent describe or undefined if the root.\n */\nangular.scenario.Describe = function(descName, parent) {\n  this.only = parent && parent.only;\n  this.beforeEachFns = [];\n  this.afterEachFns = [];\n  this.its = [];\n  this.children = [];\n  this.name = descName;\n  this.parent = parent;\n  this.id = angular.scenario.Describe.id++;\n\n  /**\n   * Calls all before functions.\n   */\n  var beforeEachFns = this.beforeEachFns;\n  this.setupBefore = function() {\n    if (parent) parent.setupBefore.call(this);\n    angular.forEach(beforeEachFns, function(fn) { fn.call(this); }, this);\n  };\n\n  /**\n   * Calls all after functions.\n   */\n  var afterEachFns = this.afterEachFns;\n  this.setupAfter  = function() {\n    angular.forEach(afterEachFns, function(fn) { fn.call(this); }, this);\n    if (parent) parent.setupAfter.call(this);\n  };\n};\n\n// Shared Unique ID generator for every describe block\nangular.scenario.Describe.id = 0;\n\n// Shared Unique ID generator for every it (spec)\nangular.scenario.Describe.specId = 0;\n\n/**\n * Defines a block to execute before each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.beforeEach = function(body) {\n  this.beforeEachFns.push(body);\n};\n\n/**\n * Defines a block to execute after each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.afterEach = function(body) {\n  this.afterEachFns.push(body);\n};\n\n/**\n * Creates a new describe block that's a child of this one.\n *\n * @param {string} name Name of the block. Appended to the parent block's name.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.describe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Same as describe() but makes ddescribe blocks the only to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.ddescribe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  child.only = true;\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Use to disable a describe block.\n */\nangular.scenario.Describe.prototype.xdescribe = angular.noop;\n\n/**\n * Defines a test.\n *\n * @param {string} name Name of the test.\n * @param {function()} vody Body of the block.\n */\nangular.scenario.Describe.prototype.it = function(name, body) {\n  this.its.push({\n    id: angular.scenario.Describe.specId++,\n    definition: this,\n    only: this.only,\n    name: name,\n    before: this.setupBefore,\n    body: body,\n    after: this.setupAfter\n  });\n};\n\n/**\n * Same as it() but makes iit tests the only test to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.iit = function(name, body) {\n  this.it.apply(this, arguments);\n  this.its[this.its.length-1].only = true;\n};\n\n/**\n * Use to disable a test block.\n */\nangular.scenario.Describe.prototype.xit = angular.noop;\n\n/**\n * Gets an array of functions representing all the tests (recursively).\n * that can be executed with SpecRunner's.\n *\n * @return {Array<Object>} Array of it blocks {\n *   definition : Object // parent Describe\n *   only: boolean\n *   name: string\n *   before: Function\n *   body: Function\n *   after: Function\n *  }\n */\nangular.scenario.Describe.prototype.getSpecs = function() {\n  var specs = arguments[0] || [];\n  angular.forEach(this.children, function(child) {\n    child.getSpecs(specs);\n  });\n  angular.forEach(this.its, function(it) {\n    specs.push(it);\n  });\n  var only = [];\n  angular.forEach(specs, function(it) {\n    if (it.only) {\n      only.push(it);\n    }\n  });\n  return (only.length && only) || specs;\n};\n\n/**\n * A future action in a spec.\n *\n * @param {string} name of the future action\n * @param {function()} future callback(error, result)\n * @param {function()} Optional. function that returns the file/line number.\n */\nangular.scenario.Future = function(name, behavior, line) {\n  this.name = name;\n  this.behavior = behavior;\n  this.fulfilled = false;\n  this.value = undefined;\n  this.parser = angular.identity;\n  this.line = line || function() { return ''; };\n};\n\n/**\n * Executes the behavior of the closure.\n *\n * @param {function()} doneFn Callback function(error, result)\n */\nangular.scenario.Future.prototype.execute = function(doneFn) {\n  var self = this;\n  this.behavior(function(error, result) {\n    self.fulfilled = true;\n    if (result) {\n      try {\n        result = self.parser(result);\n      } catch(e) {\n        error = e;\n      }\n    }\n    self.value = error || result;\n    doneFn(error, result);\n  });\n};\n\n/**\n * Configures the future to convert it's final with a function fn(value)\n *\n * @param {function()} fn function(value) that returns the parsed value\n */\nangular.scenario.Future.prototype.parsedWith = function(fn) {\n  this.parser = fn;\n  return this;\n};\n\n/**\n * Configures the future to parse it's final value from JSON\n * into objects.\n */\nangular.scenario.Future.prototype.fromJson = function() {\n  return this.parsedWith(angular.fromJson);\n};\n\n/**\n * Configures the future to convert it's final value from objects\n * into JSON.\n */\nangular.scenario.Future.prototype.toJson = function() {\n  return this.parsedWith(angular.toJson);\n};\n\n/**\n * Maintains an object tree from the runner events.\n *\n * @param {Object} runner The scenario Runner instance to connect to.\n *\n * TODO(esprehn): Every output type creates one of these, but we probably\n *  want one global shared instance. Need to handle events better too\n *  so the HTML output doesn't need to do spec model.getSpec(spec.id)\n *  silliness.\n *\n * TODO(vojta) refactor on, emit methods (from all objects) - use inheritance\n */\nangular.scenario.ObjectModel = function(runner) {\n  var self = this;\n\n  this.specMap = {};\n  this.listeners = [];\n  this.value = {\n    name: '',\n    children: {}\n  };\n\n  runner.on('SpecBegin', function(spec) {\n    var block = self.value,\n        definitions = [];\n\n    angular.forEach(self.getDefinitionPath(spec), function(def) {\n      if (!block.children[def.name]) {\n        block.children[def.name] = {\n          id: def.id,\n          name: def.name,\n          children: {},\n          specs: {}\n        };\n      }\n      block = block.children[def.name];\n      definitions.push(def.name);\n    });\n\n    var it = self.specMap[spec.id] =\n             block.specs[spec.name] =\n             new angular.scenario.ObjectModel.Spec(spec.id, spec.name, definitions);\n\n    // forward the event\n    self.emit('SpecBegin', it);\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var it = self.getSpec(spec.id);\n    it.status = 'error';\n    it.error = error;\n\n    // forward the event\n    self.emit('SpecError', it, error);\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    complete(it);\n\n    // forward the event\n    self.emit('SpecEnd', it);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var it = self.getSpec(spec.id);\n    var step = new angular.scenario.ObjectModel.Step(step.name);\n    it.steps.push(step);\n\n    // forward the event\n    self.emit('StepBegin', it, step);\n  });\n\n  runner.on('StepEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    var step = it.getLastStep();\n    if (step.name !== step.name)\n      throw 'Events fired in the wrong order. Step names don\\'t match.';\n    complete(step);\n\n    // forward the event\n    self.emit('StepEnd', it, step);\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('failure', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepFailure', it, modelStep, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('error', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepError', it, modelStep, error);\n  });\n\n  runner.on('RunnerBegin', function() {\n    self.emit('RunnerBegin');\n  });\n  runner.on('RunnerEnd', function() {\n    self.emit('RunnerEnd');\n  });\n\n  function complete(item) {\n    item.endTime = new Date().getTime();\n    item.duration = item.endTime - item.startTime;\n    item.status = item.status || 'success';\n  }\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName Name of the event to add a handler for\n * @param {function()} listener Function that will be called when event is fired\n */\nangular.scenario.ObjectModel.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.ObjectModel.prototype.emit = function(eventName) {\n  var self = this,\n      args = Array.prototype.slice.call(arguments, 1),\n      eventName = eventName.toLowerCase();\n\n  if (this.listeners[eventName]) {\n    angular.forEach(this.listeners[eventName], function(listener) {\n      listener.apply(self, args);\n    });\n  }\n};\n\n/**\n * Computes the path of definition describe blocks that wrap around\n * this spec.\n *\n * @param spec Spec to compute the path for.\n * @return {Array<Describe>} The describe block path\n */\nangular.scenario.ObjectModel.prototype.getDefinitionPath = function(spec) {\n  var path = [];\n  var currentDefinition = spec.definition;\n  while (currentDefinition && currentDefinition.name) {\n    path.unshift(currentDefinition);\n    currentDefinition = currentDefinition.parent;\n  }\n  return path;\n};\n\n/**\n * Gets a spec by id.\n *\n * @param {string} The id of the spec to get the object for.\n * @return {Object} the Spec instance\n */\nangular.scenario.ObjectModel.prototype.getSpec = function(id) {\n  return this.specMap[id];\n};\n\n/**\n * A single it block.\n *\n * @param {string} id Id of the spec\n * @param {string} name Name of the spec\n * @param {Array<string>=} definitionNames List of all describe block names that wrap this spec\n */\nangular.scenario.ObjectModel.Spec = function(id, name, definitionNames) {\n  this.id = id;\n  this.name = name;\n  this.startTime = new Date().getTime();\n  this.steps = [];\n  this.fullDefinitionName = (definitionNames || []).join(' ');\n};\n\n/**\n * Adds a new step to the Spec.\n *\n * @param {string} step Name of the step (really name of the future)\n * @return {Object} the added step\n */\nangular.scenario.ObjectModel.Spec.prototype.addStep = function(name) {\n  var step = new angular.scenario.ObjectModel.Step(name);\n  this.steps.push(step);\n  return step;\n};\n\n/**\n * Gets the most recent step.\n *\n * @return {Object} the step\n */\nangular.scenario.ObjectModel.Spec.prototype.getLastStep = function() {\n  return this.steps[this.steps.length-1];\n};\n\n/**\n * Set status of the Spec from given Step\n *\n * @param {angular.scenario.ObjectModel.Step} step\n */\nangular.scenario.ObjectModel.Spec.prototype.setStatusFromStep = function(step) {\n  if (!this.status || step.status == 'error') {\n    this.status = step.status;\n    this.error = step.error;\n    this.line = step.line;\n  }\n};\n\n/**\n * A single step inside a Spec.\n *\n * @param {string} step Name of the step\n */\nangular.scenario.ObjectModel.Step = function(name) {\n  this.name = name;\n  this.startTime = new Date().getTime();\n};\n\n/**\n * Helper method for setting all error status related properties\n *\n * @param {string} status\n * @param {string} error\n * @param {string} line\n */\nangular.scenario.ObjectModel.Step.prototype.setErrorStatus = function(status, error, line) {\n  this.status = status;\n  this.error = error;\n  this.line = line;\n};\n\n/**\n * Runner for scenarios\n *\n * Has to be initialized before any test is loaded,\n * because it publishes the API into window (global space).\n */\nangular.scenario.Runner = function($window) {\n  this.listeners = [];\n  this.$window = $window;\n  this.rootDescribe = new angular.scenario.Describe();\n  this.currentDescribe = this.rootDescribe;\n  this.api = {\n    it: this.it,\n    iit: this.iit,\n    xit: angular.noop,\n    describe: this.describe,\n    ddescribe: this.ddescribe,\n    xdescribe: angular.noop,\n    beforeEach: this.beforeEach,\n    afterEach: this.afterEach\n  };\n  angular.forEach(this.api, angular.bind(this, function(fn, key) {\n    this.$window[key] = angular.bind(this, fn);\n  }));\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.Runner.prototype.emit = function(eventName) {\n  var self = this;\n  var args = Array.prototype.slice.call(arguments, 1);\n  eventName = eventName.toLowerCase();\n  if (!this.listeners[eventName])\n    return;\n  angular.forEach(this.listeners[eventName], function(listener) {\n    listener.apply(self, args);\n  });\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName The name of the event to add a handler for\n * @param {string} listener The fn(...) that takes the extra arguments from emit()\n */\nangular.scenario.Runner.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Defines a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.describe = function(name, body) {\n  var self = this;\n  this.currentDescribe.describe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Same as describe, but makes ddescribe the only blocks to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.ddescribe = function(name, body) {\n  var self = this;\n  this.currentDescribe.ddescribe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Defines a test in a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.it = function(name, body) {\n  this.currentDescribe.it(name, body);\n};\n\n/**\n * Same as it, but makes iit tests the only tests to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.iit = function(name, body) {\n  this.currentDescribe.iit(name, body);\n};\n\n/**\n * Defines a function to be called before each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.beforeEach = function(body) {\n  this.currentDescribe.beforeEach(body);\n};\n\n/**\n * Defines a function to be called after each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.afterEach = function(body) {\n  this.currentDescribe.afterEach(body);\n};\n\n/**\n * Creates a new spec runner.\n *\n * @private\n * @param {Object} scope parent scope\n */\nangular.scenario.Runner.prototype.createSpecRunner_ = function(scope) {\n  var child = scope.$new();\n  var Cls = angular.scenario.SpecRunner;\n\n  // Export all the methods to child scope manually as now we don't mess controllers with scopes\n  // TODO(vojta): refactor scenario runner so that these objects are not tightly coupled as current\n  for (var name in Cls.prototype)\n    child[name] = angular.bind(child, Cls.prototype[name]);\n\n  Cls.call(child);\n  return child;\n};\n\n/**\n * Runs all the loaded tests with the specified runner class on the\n * provided application.\n *\n * @param {angular.scenario.Application} application App to remote control.\n */\nangular.scenario.Runner.prototype.run = function(application) {\n  var self = this;\n  var $root = angular.injector(['ng']).get('$rootScope');\n  angular.extend($root, this);\n  angular.forEach(angular.scenario.Runner.prototype, function(fn, name) {\n    $root[name] = angular.bind(self, fn);\n  });\n  $root.application = application;\n  $root.emit('RunnerBegin');\n  asyncForEach(this.rootDescribe.getSpecs(), function(spec, specDone) {\n    var dslCache = {};\n    var runner = self.createSpecRunner_($root);\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      dslCache[key] = fn.call($root);\n    });\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      self.$window[key] = function() {\n        var line = callerFile(3);\n        var scope = runner.$new();\n\n        // Make the dsl accessible on the current chain\n        scope.dsl = {};\n        angular.forEach(dslCache, function(fn, key) {\n          scope.dsl[key] = function() {\n            return dslCache[key].apply(scope, arguments);\n          };\n        });\n\n        // Make these methods work on the current chain\n        scope.addFuture = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFuture.apply(scope, arguments);\n        };\n        scope.addFutureAction = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFutureAction.apply(scope, arguments);\n        };\n\n        return scope.dsl[key].apply(scope, arguments);\n      };\n    });\n    runner.run(spec, function() {\n      runner.$destroy();\n      specDone.apply(this, arguments);\n    });\n  },\n  function(error) {\n    if (error) {\n      self.emit('RunnerError', error);\n    }\n    self.emit('RunnerEnd');\n  });\n};\n\n/**\n * This class is the \"this\" of the it/beforeEach/afterEach method.\n * Responsibilities:\n *   - \"this\" for it/beforeEach/afterEach\n *   - keep state for single it/beforeEach/afterEach execution\n *   - keep track of all of the futures to execute\n *   - run single spec (execute each future)\n */\nangular.scenario.SpecRunner = function() {\n  this.futures = [];\n  this.afterIndex = 0;\n};\n\n/**\n * Executes a spec which is an it block with associated before/after functions\n * based on the describe nesting.\n *\n * @param {Object} spec A spec object\n * @param {function()} specDone function that is called when the spec finshes. Function(error, index)\n */\nangular.scenario.SpecRunner.prototype.run = function(spec, specDone) {\n  var self = this;\n  this.spec = spec;\n\n  this.emit('SpecBegin', spec);\n\n  try {\n    spec.before.call(this);\n    spec.body.call(this);\n    this.afterIndex = this.futures.length;\n    spec.after.call(this);\n  } catch (e) {\n    this.emit('SpecError', spec, e);\n    this.emit('SpecEnd', spec);\n    specDone();\n    return;\n  }\n\n  var handleError = function(error, done) {\n    if (self.error) {\n      return done();\n    }\n    self.error = true;\n    done(null, self.afterIndex);\n  };\n\n  asyncForEach(\n    this.futures,\n    function(future, futureDone) {\n      self.step = future;\n      self.emit('StepBegin', spec, future);\n      try {\n        future.execute(function(error) {\n          if (error) {\n            self.emit('StepFailure', spec, future, error);\n            self.emit('StepEnd', spec, future);\n            return handleError(error, futureDone);\n          }\n          self.emit('StepEnd', spec, future);\n          self.$window.setTimeout(function() { futureDone(); }, 0);\n        });\n      } catch (e) {\n        self.emit('StepError', spec, future, e);\n        self.emit('StepEnd', spec, future);\n        handleError(e, futureDone);\n      }\n    },\n    function(e) {\n      if (e) {\n        self.emit('SpecError', spec, e);\n      }\n      self.emit('SpecEnd', spec);\n      // Call done in a timeout so exceptions don't recursively\n      // call this function\n      self.$window.setTimeout(function() { specDone(); }, 0);\n    }\n  );\n};\n\n/**\n * Adds a new future action.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFuture = function(name, behavior, line) {\n  var future = new angular.scenario.Future(name, angular.bind(this, behavior), line);\n  this.futures.push(future);\n  return future;\n};\n\n/**\n * Adds a new future action to be executed on the application window.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior, line) {\n  var self = this;\n  var NG = /\\[ng\\\\\\:/;\n  return this.addFuture(name, function(done) {\n    this.application.executeAction(function($window, $document) {\n\n      //TODO(esprehn): Refactor this so it doesn't need to be in here.\n      $document.elements = function(selector) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        selector = (self.selector || '') + ' ' + (selector || '');\n        selector = _jQuery.trim(selector) || '*';\n        angular.forEach(args, function(value, index) {\n          selector = selector.replace('$' + (index + 1), value);\n        });\n        var result = $document.find(selector);\n        if (selector.match(NG)) {\n          angular.forEach(['[ng-','[data-ng-','[x-ng-'], function(value, index){\n            result = result.add(selector.replace(NG, value), $document);\n          });\n        }\n        if (!result.length) {\n          throw {\n            type: 'selector',\n            message: 'Selector ' + selector + ' did not match any elements.'\n          };\n        }\n\n        return result;\n      };\n\n      try {\n        behavior.call(self, $window, $document, done);\n      } catch(e) {\n        if (e.type && e.type === 'selector') {\n          done(e.message);\n        } else {\n          throw e;\n        }\n      }\n    });\n  }, line);\n};\n\n/**\n * Shared DSL statements that are useful to all scenarios.\n */\n\n /**\n * Usage:\n *    pause() pauses until you call resume() in the console\n */\nangular.scenario.dsl('pause', function() {\n  return function() {\n    return this.addFuture('pausing for you to resume', function(done) {\n      this.emit('InteractivePause', this.spec, this.step);\n      this.$window.resume = function() { done(); };\n    });\n  };\n});\n\n/**\n * Usage:\n *    sleep(seconds) pauses the test for specified number of seconds\n */\nangular.scenario.dsl('sleep', function() {\n  return function(time) {\n    return this.addFuture('sleep for ' + time + ' seconds', function(done) {\n      this.$window.setTimeout(function() { done(null, time * 1000); }, time * 1000);\n    });\n  };\n});\n\n/**\n * Usage:\n *    browser().navigateTo(url) Loads the url into the frame\n *    browser().navigateTo(url, fn) where fn(url) is called and returns the URL to navigate to\n *    browser().reload() refresh the page (reload the same URL)\n *    browser().window.href() window.location.href\n *    browser().window.path() window.location.pathname\n *    browser().window.search() window.location.search\n *    browser().window.hash() window.location.hash without # prefix\n *    browser().location().url() see ng.$location#url\n *    browser().location().path() see ng.$location#path\n *    browser().location().search() see ng.$location#search\n *    browser().location().hash() see ng.$location#hash\n */\nangular.scenario.dsl('browser', function() {\n  var chain = {};\n\n  chain.navigateTo = function(url, delegate) {\n    var application = this.application;\n    return this.addFuture(\"browser navigate to '\" + url + \"'\", function(done) {\n      if (delegate) {\n        url = delegate.call(this, url);\n      }\n      application.navigateTo(url, function() {\n        done(null, url);\n      }, done);\n    });\n  };\n\n  chain.reload = function() {\n    var application = this.application;\n    return this.addFutureAction('browser reload', function($window, $document, done) {\n      var href = $window.location.href;\n      application.navigateTo(href, function() {\n        done(null, href);\n      }, done);\n    });\n  };\n\n  chain.window = function() {\n    var api = {};\n\n    api.href = function() {\n      return this.addFutureAction('window.location.href', function($window, $document, done) {\n        done(null, $window.location.href);\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('window.location.path', function($window, $document, done) {\n        done(null, $window.location.pathname);\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('window.location.search', function($window, $document, done) {\n        done(null, $window.location.search);\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('window.location.hash', function($window, $document, done) {\n        done(null, $window.location.hash.replace('#', ''));\n      });\n    };\n\n    return api;\n  };\n\n  chain.location = function() {\n    var api = {};\n\n    api.url = function() {\n      return this.addFutureAction('$location.url()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').url());\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('$location.path()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').path());\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('$location.search()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').search());\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('$location.hash()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').hash());\n      });\n    };\n\n    return api;\n  };\n\n  return function() {\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    expect(future).{matcher} where matcher is one of the matchers defined\n *    with angular.scenario.matcher\n *\n * ex. expect(binding(\"name\")).toEqual(\"Elliott\")\n */\nangular.scenario.dsl('expect', function() {\n  var chain = angular.extend({}, angular.scenario.matcher);\n\n  chain.not = function() {\n    this.inverse = true;\n    return chain;\n  };\n\n  return function(future) {\n    this.future = future;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    using(selector, label) scopes the next DSL element selection\n *\n * ex.\n *   using('#foo', \"'Foo' text field\").input('bar')\n */\nangular.scenario.dsl('using', function() {\n  return function(selector, label) {\n    this.selector = _jQuery.trim((this.selector||'') + ' ' + selector);\n    if (angular.isString(label) && label.length) {\n      this.label = label + ' ( ' + this.selector + ' )';\n    } else {\n      this.label = this.selector;\n    }\n    return this.dsl;\n  };\n});\n\n/**\n * Usage:\n *    binding(name) returns the value of the first matching binding\n */\nangular.scenario.dsl('binding', function() {\n  return function(name) {\n    return this.addFutureAction(\"select binding '\" + name + \"'\", function($window, $document, done) {\n      var values = $document.elements().bindings($window.angular.element, name);\n      if (!values.length) {\n        return done(\"Binding selector '\" + name + \"' did not match.\");\n      }\n      done(null, values[0]);\n    });\n  };\n});\n\n/**\n * Usage:\n *    input(name).enter(value) enters value in input with specified name\n *    input(name).check() checks checkbox\n *    input(name).select(value) selects the radio button with specified name/value\n *    input(name).val() returns the value of the input.\n */\nangular.scenario.dsl('input', function() {\n  var chain = {};\n  var supportInputEvent =  'oninput' in document.createElement('div') && msie != 9;\n\n  chain.enter = function(value, event) {\n    return this.addFutureAction(\"input '\" + this.name + \"' enter '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      input.val(value);\n      input.trigger(event || (supportInputEvent ? 'input' : 'change'));\n      done();\n    });\n  };\n\n  chain.check = function() {\n    return this.addFutureAction(\"checkbox '\" + this.name + \"' toggle\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':checkbox');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.select = function(value) {\n    return this.addFutureAction(\"radio button '\" + this.name + \"' toggle '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.\n        elements('[ng\\\\:model=\"$1\"][value=\"$2\"]', this.name, value).filter(':radio');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.val = function() {\n    return this.addFutureAction(\"return input val\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      done(null,input.val());\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n\n/**\n * Usage:\n *    repeater('#products table', 'Product List').count() number of rows\n *    repeater('#products table', 'Product List').row(1) all bindings in row as an array\n *    repeater('#products table', 'Product List').column('product.name') all values across all rows in an array\n */\nangular.scenario.dsl('repeater', function() {\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.column = function(binding) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' column '\" + binding + \"'\", function($window, $document, done) {\n      done(null, $document.elements().bindings($window.angular.element, binding));\n    });\n  };\n\n  chain.row = function(index) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' row '\" + index + \"'\", function($window, $document, done) {\n      var matches = $document.elements().slice(index, index + 1);\n      if (!matches.length)\n        return done('row ' + index + ' out of bounds');\n      done(null, matches.bindings($window.angular.element));\n    });\n  };\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    select(name).option('value') select one option\n *    select(name).options('value1', 'value2', ...) select options from a multi select\n */\nangular.scenario.dsl('select', function() {\n  var chain = {};\n\n  chain.option = function(value) {\n    return this.addFutureAction(\"select '\" + this.name + \"' option '\" + value + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[ng\\\\:model=\"$1\"]', this.name);\n      var option = select.find('option[value=\"' + value + '\"]');\n      if (option.length) {\n        select.val(value);\n      } else {\n        option = select.find('option:contains(\"' + value + '\")');\n        if (option.length) {\n          select.val(option.val());\n        }\n      }\n      select.trigger('change');\n      done();\n    });\n  };\n\n  chain.options = function() {\n    var values = arguments;\n    return this.addFutureAction(\"select '\" + this.name + \"' options '\" + values + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[multiple][ng\\\\:model=\"$1\"]', this.name);\n      select.val(values);\n      select.trigger('change');\n      done();\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    element(selector, label).count() get the number of elements that match selector\n *    element(selector, label).click() clicks an element\n *    element(selector, label).query(fn) executes fn(selectedElements, done)\n *    element(selector, label).{method}() gets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(value) sets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(key) gets the value (as defined by jQuery, ex. attr)\n *    element(selector, label).{method}(key, value) sets the value (as defined by jQuery, ex. attr)\n */\nangular.scenario.dsl('element', function() {\n  var KEY_VALUE_METHODS = ['attr', 'css', 'prop'];\n  var VALUE_METHODS = [\n    'val', 'text', 'html', 'height', 'innerHeight', 'outerHeight', 'width',\n    'innerWidth', 'outerWidth', 'position', 'scrollLeft', 'scrollTop', 'offset'\n  ];\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.click = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' click\", function($window, $document, done) {\n      var elements = $document.elements();\n      var href = elements.attr('href');\n      var eventProcessDefault = elements.trigger('click')[0];\n\n      if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {\n        this.application.navigateTo(href, function() {\n          done();\n        }, done);\n      } else {\n        done();\n      }\n    });\n  };\n\n  chain.query = function(fn) {\n    return this.addFutureAction('element ' + this.label + ' custom query', function($window, $document, done) {\n      fn.call(this, $document.elements(), done);\n    });\n  };\n\n  angular.forEach(KEY_VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(name, value) {\n      var args = arguments,\n          futureName = (args.length == 1)\n              ? \"element '\" + this.label + \"' get \" + methodName + \" '\" + name + \"'\"\n              : \"element '\" + this.label + \"' set \" + methodName + \" '\" + name + \"' to \" + \"'\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  angular.forEach(VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(value) {\n      var args = arguments,\n          futureName = (args.length == 0)\n              ? \"element '\" + this.label + \"' \" + methodName\n              : futureName = \"element '\" + this.label + \"' set \" + methodName + \" to '\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Matchers for implementing specs. Follows the Jasmine spec conventions.\n */\n\nangular.scenario.matcher('toEqual', function(expected) {\n  return angular.equals(this.actual, expected);\n});\n\nangular.scenario.matcher('toBe', function(expected) {\n  return this.actual === expected;\n});\n\nangular.scenario.matcher('toBeDefined', function() {\n  return angular.isDefined(this.actual);\n});\n\nangular.scenario.matcher('toBeTruthy', function() {\n  return this.actual;\n});\n\nangular.scenario.matcher('toBeFalsy', function() {\n  return !this.actual;\n});\n\nangular.scenario.matcher('toMatch', function(expected) {\n  return new RegExp(expected).test(this.actual);\n});\n\nangular.scenario.matcher('toBeNull', function() {\n  return this.actual === null;\n});\n\nangular.scenario.matcher('toContain', function(expected) {\n  return includes(this.actual, expected);\n});\n\nangular.scenario.matcher('toBeLessThan', function(expected) {\n  return this.actual < expected;\n});\n\nangular.scenario.matcher('toBeGreaterThan', function(expected) {\n  return this.actual > expected;\n});\n\n/**\n * User Interface for the Scenario Runner.\n *\n * TODO(esprehn): This should be refactored now that ObjectModel exists\n *  to use angular bindings for the UI.\n */\nangular.scenario.output('html', function(context, runner, model) {\n  var specUiMap = {},\n      lastStepUiMap = {};\n\n  context.append(\n    '<div id=\"header\">' +\n    '  <h1><span class=\"angular\">AngularJS</span>: Scenario Test Runner</h1>' +\n    '  <ul id=\"status-legend\" class=\"status-display\">' +\n    '    <li class=\"status-error\">0 Errors</li>' +\n    '    <li class=\"status-failure\">0 Failures</li>' +\n    '    <li class=\"status-success\">0 Passed</li>' +\n    '  </ul>' +\n    '</div>' +\n    '<div id=\"specs\">' +\n    '  <div class=\"test-children\"></div>' +\n    '</div>'\n  );\n\n  runner.on('InteractivePause', function(spec) {\n    var ui = lastStepUiMap[spec.id];\n    ui.find('.test-title').\n      html('paused... <a href=\"javascript:resume()\">resume</a> when ready.');\n  });\n\n  runner.on('SpecBegin', function(spec) {\n    var ui = findContext(spec);\n    ui.find('> .tests').append(\n      '<li class=\"status-pending test-it\"></li>'\n    );\n    ui = ui.find('> .tests li:last');\n    ui.append(\n      '<div class=\"test-info\">' +\n      '  <p class=\"test-title\">' +\n      '    <span class=\"timer-result\"></span>' +\n      '    <span class=\"test-name\"></span>' +\n      '  </p>' +\n      '</div>' +\n      '<div class=\"scrollpane\">' +\n      '  <ol class=\"test-actions\"></ol>' +\n      '</div>'\n    );\n    ui.find('> .test-info .test-name').text(spec.name);\n    ui.find('> .test-info').click(function() {\n      var scrollpane = ui.find('> .scrollpane');\n      var actions = scrollpane.find('> .test-actions');\n      var name = context.find('> .test-info .test-name');\n      if (actions.find(':visible').length) {\n        actions.hide();\n        name.removeClass('open').addClass('closed');\n      } else {\n        actions.show();\n        scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n        name.removeClass('closed').addClass('open');\n      }\n    });\n\n    specUiMap[spec.id] = ui;\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var ui = specUiMap[spec.id];\n    ui.append('<pre></pre>');\n    ui.find('> pre').text(formatException(error));\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    ui.removeClass('status-pending');\n    ui.addClass('status-' + spec.status);\n    ui.find(\"> .test-info .timer-result\").text(spec.duration + \"ms\");\n    if (spec.status === 'success') {\n      ui.find('> .test-info .test-name').addClass('closed');\n      ui.find('> .scrollpane .test-actions').hide();\n    }\n    updateTotals(spec.status);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    ui.find('> .scrollpane .test-actions').append('<li class=\"status-pending\"></li>');\n    var stepUi = lastStepUiMap[spec.id] = ui.find('> .scrollpane .test-actions li:last');\n    stepUi.append(\n      '<div class=\"timer-result\"></div>' +\n      '<div class=\"test-title\"></div>'\n    );\n    stepUi.find('> .test-title').text(step.name);\n    var scrollpane = stepUi.parents('.scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepEnd', function(spec, step) {\n    var stepUi = lastStepUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    stepUi.find('.timer-result').text(step.duration + 'ms');\n    stepUi.removeClass('status-pending');\n    stepUi.addClass('status-' + step.status);\n    var scrollpane = specUiMap[spec.id].find('> .scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  /**\n   * Finds the context of a spec block defined by the passed definition.\n   *\n   * @param {Object} The definition created by the Describe object.\n   */\n  function findContext(spec) {\n    var currentContext = context.find('#specs');\n    angular.forEach(model.getDefinitionPath(spec), function(defn) {\n      var id = 'describe-' + defn.id;\n      if (!context.find('#' + id).length) {\n        currentContext.find('> .test-children').append(\n          '<div class=\"test-describe\" id=\"' + id + '\">' +\n          '  <h2></h2>' +\n          '  <div class=\"test-children\"></div>' +\n          '  <ul class=\"tests\"></ul>' +\n          '</div>'\n        );\n        context.find('#' + id).find('> h2').text('describe: ' + defn.name);\n      }\n      currentContext = context.find('#' + id);\n    });\n    return context.find('#describe-' + spec.definition.id);\n  }\n\n  /**\n   * Updates the test counter for the status.\n   *\n   * @param {string} the status.\n   */\n  function updateTotals(status) {\n    var legend = context.find('#status-legend .status-' + status);\n    var parts = legend.text().split(' ');\n    var value = (parts[0] * 1) + 1;\n    legend.text(value + ' ' + parts[1]);\n  }\n\n  /**\n   * Add an error to a step.\n   *\n   * @param {Object} The JQuery wrapped context\n   * @param {function()} fn() that should return the file/line number of the error\n   * @param {Object} the error.\n   */\n  function addError(context, line, error) {\n    context.find('.test-title').append('<pre></pre>');\n    var message = _jQuery.trim(line() + '\\n\\n' + formatException(error));\n    context.find('.test-title pre:last').text(message);\n  }\n});\n\n/**\n * Generates JSON output into a context.\n */\nangular.scenario.output('json', function(context, runner, model) {\n  model.on('RunnerEnd', function() {\n    context.text(angular.toJson(model.value));\n  });\n});\n\n/**\n * Generates XML output into a context.\n */\nangular.scenario.output('xml', function(context, runner, model) {\n  var $ = function(args) {return new context.init(args);};\n  model.on('RunnerEnd', function() {\n    var scenario = $('<scenario></scenario>');\n    context.append(scenario);\n    serializeXml(scenario, model.value);\n  });\n\n  /**\n   * Convert the tree into XML.\n   *\n   * @param {Object} context jQuery context to add the XML to.\n   * @param {Object} tree node to serialize\n   */\n  function serializeXml(context, tree) {\n     angular.forEach(tree.children, function(child) {\n       var describeContext = $('<describe></describe>');\n       describeContext.attr('id', child.id);\n       describeContext.attr('name', child.name);\n       context.append(describeContext);\n       serializeXml(describeContext, child);\n     });\n     var its = $('<its></its>');\n     context.append(its);\n     angular.forEach(tree.specs, function(spec) {\n       var it = $('<it></it>');\n       it.attr('id', spec.id);\n       it.attr('name', spec.name);\n       it.attr('duration', spec.duration);\n       it.attr('status', spec.status);\n       its.append(it);\n       angular.forEach(spec.steps, function(step) {\n         var stepContext = $('<step></step>');\n         stepContext.attr('name', step.name);\n         stepContext.attr('duration', step.duration);\n         stepContext.attr('status', step.status);\n         it.append(stepContext);\n         if (step.error) {\n           var error = $('<error></error>');\n           stepContext.append(error);\n           error.text(formatException(stepContext.error));\n         }\n       });\n     });\n   }\n});\n\n/**\n * Creates a global value $result with the result of the runner.\n */\nangular.scenario.output('object', function(context, runner, model) {\n  runner.$window.$result = model.value;\n});\nbindJQuery();\npublishExternalAPI(angular);\n\nvar $runner = new angular.scenario.Runner(window),\n    scripts = document.getElementsByTagName('script'),\n    script = scripts[scripts.length - 1],\n    config = {};\n\nangular.forEach(script.attributes, function(attr) {\n  var match = attr.name.match(/ng[:\\-](.*)/);\n  if (match) {\n    config[match[1]] = attr.value || true;\n  }\n});\n\nif (config.autotest) {\n  JQLite(document).ready(function() {\n    angular.scenario.setUpAndRun(config);\n  });\n}\n})(window, document);\n\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n\\n[ng\\\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\\n.ng-cloak, .x-ng-cloak {\\n  display: none;\\n}\\n\\nng\\\\:form {\\n  display: block;\\n}\\n</style>');\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n/* CSS Document */\\n\\n/** Structure */\\nbody {\\n  font-family: Arial, sans-serif;\\n  margin: 0;\\n  font-size: 14px;\\n}\\n\\n#system-error {\\n  font-size: 1.5em;\\n  text-align: center;\\n}\\n\\n#json, #xml {\\n  display: none;\\n}\\n\\n#header {\\n  position: fixed;\\n  width: 100%;\\n}\\n\\n#specs {\\n  padding-top: 50px;\\n}\\n\\n#header .angular {\\n  font-family: Courier New, monospace;\\n  font-weight: bold;\\n}\\n\\n#header h1 {\\n  font-weight: normal;\\n  float: left;\\n  font-size: 30px;\\n  line-height: 30px;\\n  margin: 0;\\n  padding: 10px 10px;\\n  height: 30px;\\n}\\n\\n#application h2,\\n#specs h2 {\\n  margin: 0;\\n  padding: 0.5em;\\n  font-size: 1.1em;\\n}\\n\\n#status-legend {\\n  margin-top: 10px;\\n  margin-right: 10px;\\n}\\n\\n#header,\\n#application,\\n.test-info,\\n.test-actions li {\\n  overflow: hidden;\\n}\\n\\n#application {\\n  margin: 10px;\\n}\\n\\n#application iframe {\\n  width: 100%;\\n  height: 758px;\\n}\\n\\n#application .popout {\\n  float: right;\\n}\\n\\n#application iframe {\\n  border: none;\\n}\\n\\n.tests li,\\n.test-actions li,\\n.test-it li,\\n.test-it ol,\\n.status-display {\\n  list-style-type: none;\\n}\\n\\n.tests,\\n.test-it ol,\\n.status-display {\\n  margin: 0;\\n  padding: 0;\\n}\\n\\n.test-info {\\n  margin-left: 1em;\\n  margin-top: 0.5em;\\n  border-radius: 8px 0 0 8px;\\n  -webkit-border-radius: 8px 0 0 8px;\\n  -moz-border-radius: 8px 0 0 8px;\\n  cursor: pointer;\\n}\\n\\n.test-info:hover .test-name {\\n  text-decoration: underline;\\n}\\n\\n.test-info .closed:before {\\n  content: \\'\\\\25b8\\\\00A0\\';\\n}\\n\\n.test-info .open:before {\\n  content: \\'\\\\25be\\\\00A0\\';\\n  font-weight: bold;\\n}\\n\\n.test-it ol {\\n  margin-left: 2.5em;\\n}\\n\\n.status-display,\\n.status-display li {\\n  float: right;\\n}\\n\\n.status-display li {\\n  padding: 5px 10px;\\n}\\n\\n.timer-result,\\n.test-title {\\n  display: inline-block;\\n  margin: 0;\\n  padding: 4px;\\n}\\n\\n.test-actions .test-title,\\n.test-actions .test-result {\\n  display: table-cell;\\n  padding-left: 0.5em;\\n  padding-right: 0.5em;\\n}\\n\\n.test-actions {\\n  display: table;\\n}\\n\\n.test-actions li {\\n  display: table-row;\\n}\\n\\n.timer-result {\\n  width: 4em;\\n  padding: 0 10px;\\n  text-align: right;\\n  font-family: monospace;\\n}\\n\\n.test-it pre,\\n.test-actions pre {\\n  clear: left;\\n  color: black;\\n  margin-left: 6em;\\n}\\n\\n.test-describe {\\n  padding-bottom: 0.5em;\\n}\\n\\n.test-describe .test-describe {\\n  margin: 5px 5px 10px 2em;\\n}\\n\\n.test-actions .status-pending .test-title:before {\\n  content: \\'\\\\00bb\\\\00A0\\';\\n}\\n\\n.scrollpane {\\n   max-height: 20em;\\n   overflow: auto;\\n}\\n\\n/** Colors */\\n\\n#header {\\n  background-color: #F2C200;\\n}\\n\\n#specs h2 {\\n  border-top: 2px solid #BABAD1;\\n}\\n\\n#specs h2,\\n#application h2 {\\n  background-color: #efefef;\\n}\\n\\n#application {\\n  border: 1px solid #BABAD1;\\n}\\n\\n.test-describe .test-describe {\\n  border-left: 1px solid #BABAD1;\\n  border-right: 1px solid #BABAD1;\\n  border-bottom: 1px solid #BABAD1;\\n}\\n\\n.status-display {\\n  border: 1px solid #777;\\n}\\n\\n.status-display .status-pending,\\n.status-pending .test-info {\\n  background-color: #F9EEBC;\\n}\\n\\n.status-display .status-success,\\n.status-success .test-info {\\n  background-color: #B1D7A1;\\n}\\n\\n.status-display .status-failure,\\n.status-failure .test-info {\\n  background-color: #FF8286;\\n}\\n\\n.status-display .status-error,\\n.status-error .test-info {\\n  background-color: black;\\n  color: white;\\n}\\n\\n.test-actions .status-success .test-title {\\n  color: #30B30A;\\n}\\n\\n.test-actions .status-failure .test-title {\\n  color: #DF0000;\\n}\\n\\n.test-actions .status-error .test-title {\\n  color: black;\\n}\\n\\n.test-actions .timer-result {\\n  color: #888;\\n}\\n</style>');"
  },
  {
    "path": "chapter6/recipe1/test/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter6/recipe2/README.md",
    "content": "# Angular Express Seed Example App\n\nBased on the [Angular Express Seed](https://github.com/btford/angular-express-seed), this simple app illustrates how to use [AngularJS](http://angularjs.org/) and [Express](http://expressjs.com/) on a [Node.js](http://nodejs.org/) server to make a simple blog."
  },
  {
    "path": "chapter6/recipe2/app.js",
    "content": "var express = require('express');\nvar app     = module.exports = express.createServer();\n\napp.configure(function(){\n  app.set('views', __dirname + '/views');\n  app.set('view engine', 'jade');\n  app.set('view options', {\n    layout: false\n  });\n  app.use(express.bodyParser());\n  app.use(express.methodOverride());\n  app.use(express.static(__dirname + '/public'));\n  app.use(app.router);\n});\n\napp.configure('development', function(){\n  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));\n});\n\napp.get('/', function(req, res) {\n  res.render('index');\n});\n\napp.get('/partials/:name', function (req, res) {\n  var name = req.params.name;\n  res.render('partials/' + name);\n});\n\napp.get('*', function(req, res) {\n  res.redirect('/');\n});\n\napp.listen(3000, function(){\n  console.log(\"Express server listening on port %d in %s mode\", app.address().port, app.settings.env);\n});\n"
  },
  {
    "path": "chapter6/recipe2/package.json",
    "content": "{\n    \"name\": \"application-name\"\n  , \"version\": \"0.0.1\"\n  , \"private\": true\n  , \"dependencies\": {\n      \"express\": \"2.5.10\"\n    , \"jade\": \">= 0.0.1\"\n  }\n}"
  },
  {
    "path": "chapter6/recipe2/public/css/app.css",
    "content": "/* app css stylesheet */\n\n.menu {\n  list-style: none;\n  border-bottom: 0.1em solid black;\n  margin-bottom: 2em;\n  padding: 0 0 0.5em;\n}\n\n.menu:before {\n  content: \"[\";\n}\n\n.menu:after {\n  content: \"]\";\n}\n\n.menu > li {\n  display: inline;\n}\n\n.menu > li:before {\n  content: \"|\";\n  padding-right: 0.3em;\n}\n\n.menu > li:nth-child(1):before {\n  content: \"\";\n  padding: 0;\n}\n"
  },
  {
    "path": "chapter6/recipe2/public/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter6/recipe2/public/js/app.js",
    "content": "'use strict';\n\n// Declare app level module which depends on filters, and services\nvar app = angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngResource']);\n\napp.config(function($routeProvider, $locationProvider) {\n  $locationProvider.html5Mode(true);\n  $routeProvider.\n    when(\"/persons\", { templateUrl: \"partials/index.jade\", controller: \"PersonIndexCtrl\" }).\n    when(\"/persons/:id\", { templateUrl: \"partials/show.jade\", controller: \"PersonShowCtrl\" }).\n    otherwise( { redirectTo: \"/persons\" });\n});"
  },
  {
    "path": "chapter6/recipe2/public/js/controllers.js",
    "content": "app.factory(\"Person\", function() {\n\n  var persons = [\n    { name: \"Peter\", age: 25, id: 1 },\n    { name: \"Stefan\", age: 35, id: 2 },\n    { name: \"Agnes\", age: 22, id: 3 }\n  ];\n\n  return {\n    all: function() {\n      return persons;\n    },\n    get: function(id) {\n      var result = null;\n      angular.forEach(persons, function(p) {\n        if (p.id == id) result = p;\n      });\n      return result;\n    }\n  };\n});\n\napp.controller(\"PersonIndexCtrl\", function($scope, Person) {\n  $scope.persons = Person.all();\n});\n\napp.controller(\"PersonShowCtrl\", function($scope, $routeParams, Person) {\n  $scope.person = Person.get($routeParams.id);\n});"
  },
  {
    "path": "chapter6/recipe2/public/js/directives.js",
    "content": "'use strict';\n\n/* Directives */\n\n\nangular.module('myApp.directives', []).\n  directive('appVersion', ['version', function(version) {\n    return function(scope, elm, attrs) {\n      elm.text(version);\n    };\n  }]);\n"
  },
  {
    "path": "chapter6/recipe2/public/js/filters.js",
    "content": "'use strict';\n\n/* Filters */\n\nangular.module('myApp.filters', []).\n  filter('interpolate', ['version', function(version) {\n    return function(text) {\n      return String(text).replace(/\\%VERSION\\%/mg, version);\n    }\n  }]);\n"
  },
  {
    "path": "chapter6/recipe2/public/js/lib/angular/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngCookies\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookies\n   * @requires $browser\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from\n   * this object, new cookies are created/deleted at the end of current $eval.\n   *\n   * @example\n   */\n   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for(name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            if (angular.isDefined(lastCookies[name])) {\n              cookies[name] = lastCookies[name];\n            } else {\n              delete cookies[name];\n            }\n          } else if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated){\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   * @example\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#get\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          return angular.fromJson($cookies[key]);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#put\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#remove\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter6/recipe2/public/js/lib/angular/angular-loader.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n\n(\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n'use strict';\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n)(window);\n\n/**\n * Closure compiler type information\n *\n * @typedef { {\n *   requires: !Array.<string>,\n *   invokeQueue: !Array.<Array.<*>>,\n *\n *   service: function(string, Function):angular.Module,\n *   factory: function(string, Function):angular.Module,\n *   value: function(string, *):angular.Module,\n *\n *   filter: function(string, Function):angular.Module,\n *\n *   init: function(Function):angular.Module\n * } }\n */\nangular.Module;\n\n"
  },
  {
    "path": "chapter6/recipe2/public/js/lib/angular/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n /**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` – {string} – The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` – {object=} – Optional set of pre-bound parameters for this action.\n *   - isArray – {boolean=} – If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n  /**\n   * We need our custom mehtod because encodeURIComponent is too aggressive and doesn't follow\n   * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n   * segments:\n   *    segment       = *pchar\n   *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n   *    pct-encoded   = \"%\" HEXDIG HEXDIG\n   *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n   *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n   *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n   */\n  function encodeUriSegment(val) {\n    return encodeUriQuery(val, true).\n      replace(/%26/gi, '&').\n      replace(/%3D/gi, '=').\n      replace(/%2B/gi, '+');\n  }\n\n\n  /**\n   * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n   * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n   * encoded per http://tools.ietf.org/html/rfc3986:\n   *    query       = *( pchar / \"/\" / \"?\" )\n   *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n   *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n   *    pct-encoded   = \"%\" HEXDIG HEXDIG\n   *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n   *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n   */\n  function encodeUriQuery(val, pctEncodeSpaces) {\n    return encodeURIComponent(val).\n      replace(/%40/gi, '@').\n      replace(/%3A/gi, ':').\n      replace(/%24/g, '$').\n      replace(/%2C/gi, ',').\n      replace((pctEncodeSpaces ? null : /%20/g), '+');\n  }\n\n  function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"/?:\" + urlParam + \"(\\\\W)\", \"g\"), '$1');\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.bind = function(additionalParamDefaults){\n          return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter6/recipe2/public/js/lib/angular/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             '<p style=\"color:blue\">an html\\n' +\n             '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n             'snippet</p>';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n          Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n           <table>\n             <tr>\n               <td>Filter</td>\n               <td>Source</td>\n               <td>Rendered</td>\n             </tr>\n             <tr id=\"html-filter\">\n               <td>html filter</td>\n               <td>\n                 <pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre>\n               </td>\n               <td>\n                 <div ng-bind-html=\"snippet\"></div>\n               </td>\n             </tr>\n             <tr id=\"escaped-html\">\n               <td>no filter</td>\n               <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind=\"snippet\"></div></td>\n             </tr>\n             <tr id=\"html-unsafe-filter\">\n               <td>unsafe html filter</td>\n               <td><pre>&lt;div ng-bind-html-unsafe=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind-html-unsafe=\"snippet\"></div></td>\n             </tr>\n           </table>\n         </div>\n     </doc:source>\n     <doc:scenario>\n       it('should sanitize the html snippet ', function() {\n         expect(using('#html-filter').element('div').html()).\n           toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n       });\n\n       it('should escape snippet without any filter', function() {\n         expect(using('#escaped-html').element('div').html()).\n           toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n                \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n                \"snippet&lt;/p&gt;\");\n       });\n\n       it('should inline raw snippet if filtered as unsafe', function() {\n         expect(using('#html-unsafe-filter').element(\"div\").html()).\n           toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n                \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n                \"snippet</p>\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new <b>text</b>');\n         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');\n         expect(using('#escaped-html').element('div').html()).toBe(\"new &lt;b&gt;text&lt;/b&gt;\");\n         expect(using('#html-unsafe-filter').binding(\"snippet\")).toBe('new <b>text</b>');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar $sanitize = function(html) {\n  var buf = [];\n    htmlParser(html, htmlSanitizeWriter(buf));\n    return buf.join('');\n};\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP = /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  URI_REGEXP = /^((ftp|https?):\\/\\/|mailto:|#)/,\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g; // Match everything outside of normal chars and \" (quote character)\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,aside,\" +\n        \"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,\" +\n        \"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,bdi,bdo,\" +\n        \"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,\" +\n        \"span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        index = html.indexOf(\"-->\");\n\n        if ( index >= 0 ) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'), function(all, text){\n        text = text.\n          replace(COMMENT_REGEXP, \"$1\").\n          replace(CDATA_REGEXP, \"$1\");\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n\n        return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw \"Parse Error: \" + html;\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {\n      var value = doubleQuotedValue\n        || singleQoutedValue\n        || unqoutedValue\n        || '';\n\n      attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nvar hiddenPre=document.createElement(\"pre\");\nfunction decodeEntities(value) {\n  hiddenPre.innerHTML=value.replace(/</g,\"&lt;\");\n  return hiddenPre.innerText || hiddenPre.textContent || '';\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] == true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] == true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).value('$sanitize', $sanitize);\n\n/**\n * @ngdoc directive\n * @name ngSanitize.directive:ngBindHtml\n *\n * @description\n * Creates a binding that will sanitize the result of evaluating the `expression` with the\n * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n */\nangular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);\n    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {\n      value = $sanitize(value);\n      element.html(value || '');\n    });\n  };\n}]);\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n *   plain email address links.\n *\n * @param {string} text Input text.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should linkify the snippet with urls', function() {\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('Pretty text with some links:&#10;' +\n                '<a href=\"http://angularjs.org/\">http://angularjs.org/</a>,&#10;' +\n                '<a href=\"mailto:us@somewhere.org\">us@somewhere.org</a>,&#10;' +\n                '<a href=\"mailto:another@somewhere.org\">another@somewhere.org</a>,&#10;' +\n                'and one more: <a href=\"ftp://127.0.0.1/\">ftp://127.0.0.1/</a>.');\n       });\n\n       it ('should not linkify snippet without the linky filter', function() {\n         expect(using('#escaped-html').binding('snippet')).\n           toBe(\"Pretty text with some links:\\n\" +\n                \"http://angularjs.org/,\\n\" +\n                \"mailto:us@somewhere.org,\\n\" +\n                \"another@somewhere.org,\\n\" +\n                \"and one more: ftp://127.0.0.1/.\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new http://link.');\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('new <a href=\"http://link\">http://link</a>.');\n         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', function() {\n  var LINKY_URL_REGEXP = /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s\\.\\;\\,\\(\\)\\{\\}\\<\\>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    // TODO(vojta): use $sanitize instead\n    var writer = htmlSanitizeWriter(html);\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      writer.chars(raw.substr(0, i));\n      writer.start('a', {href:url});\n      writer.chars(match[0].replace(MAILTO_REGEXP, ''));\n      writer.end('a');\n      raw = raw.substring(i + match[0].length);\n    }\n    writer.chars(raw);\n    return html.join('');\n  };\n});\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter6/recipe2/public/js/lib/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.0.3\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) !== '$' && !isFunction(o1[key]) && !equals(o1[key], o2[key])) {\n            return false;\n          }\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] && key.charAt(0) !== '$' && !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.3',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 3,\n  codeName: 'bouncy-thunder'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular privides an additional method to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeName != '#text')\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes;\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    return element.nextSibling;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key, path)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $locaiton.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n          if (lastCookies.length > 20) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because too many cookies \" +\n              \"were already set (\" + lastCookies.length + \" > 20 )\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n     var linkFns = [],\n         nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n     for(var i = 0; i < nodeList.length; i++) {\n       attrs = new Attributes();\n\n       // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n       directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n       nodeLinkFn = (directives.length)\n           ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n           : null;\n\n       childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n           ? null\n           : compileNodes(nodeList[i].childNodes,\n                nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n       linkFns.push(nodeLinkFn);\n       linkFns.push(childLinkFn);\n       linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n     }\n\n     // return a linking function if we have found anything, null otherwise\n     return linkFnFound ? compositeLinkFn : null;\n\n     function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n       var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn;\n\n       for(var i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n         node = nodeList[n];\n         nodeLinkFn = linkFns[i++];\n         childLinkFn = linkFns[i++];\n\n         if (nodeLinkFn) {\n           if (nodeLinkFn.scope) {\n             childScope = scope.$new(isObject(nodeLinkFn.scope));\n             jqLite(node).data('$scope', childScope);\n           } else {\n             childScope = scope;\n           }\n           childTranscludeFn = nodeLinkFn.transclude;\n           if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n             nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                 (function(transcludeFn) {\n                   return function(cloneFn) {\n                     var transcludeScope = scope.$new();\n\n                     return transcludeFn(transcludeScope, cloneFn).\n                         bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n             );\n           } else {\n             nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n           }\n         } else if (childLinkFn) {\n           childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n         }\n       }\n     }\n   }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite('<!-- ' + directiveName + ': ' + templateAttrs[directiveName]  + ' -->');\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler}\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programing what `try`, `catch` and `throw` keywords are to synchronous programing.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exacly match the\n   *    route definition.\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var matcher = switchRouteMatcher,\n        forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n      var regex = '^' + when.replace(/([\\.\\\\\\(\\)\\^\\$])/g, \"\\\\$1\") + '$',\n          params = [],\n          dst = {};\n      forEach(when.split(/\\W/), function(param) {\n        if (param) {\n          var paramRegExp = new RegExp(\":\" + param + \"([\\\\W])\");\n          if (regex.match(paramRegExp)) {\n            regex = regex.replace(paramRegExp, \"([^\\\\/]*)$1\");\n            params.push(param);\n          }\n        }\n      });\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = matcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             this.greeting = this.salutation + ' ' + this.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { counter = counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             counter = counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        if ($rootScope == this) return; // we can't remove the root node;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBacked\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with status\n     *       // code outside of the <200, 400) range\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n          return false; // Needed for opera\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containg forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `REQUIRED`, `URL` or `EMAIL`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.REQUIRED\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.REQUIRED = {{!!myForm.$error.REQUIRED}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            collectionLength = size(collection, true),\n            childScope,\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            key, value, // key/value of iteration\n            array, last,       // last object information {scope, element, index}\n            cursor = iterStartElement;     // current position of the node\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (collectionLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  compile: function(element, attr) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        cases = {};\n\n    element.data(NG_SWITCH, cases);\n    return function(scope, element){\n      var selectedTransclude,\n          selectedElement,\n          selectedScope;\n\n      scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n        if (selectedElement) {\n          selectedScope.$destroy();\n          selectedElement.remove();\n          selectedElement = selectedScope = null;\n        }\n        if ((selectedTransclude = cases['!' + value] || cases['?'])) {\n          scope.$eval(attr.change);\n          selectedScope = scope.$new();\n          selectedTransclude(selectedScope, function(caseElement) {\n            selectedElement = caseElement;\n            element.append(caseElement);\n          });\n        }\n      });\n    };\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  compile: function(element, attrs, transclude) {\n    var cases = element.inheritedData(NG_SWITCH);\n    assertArg(cases);\n    cases['!' + attrs.ngSwitchWhen] = transclude;\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  compile: function(element, attrs, transclude) {\n    var cases = element.inheritedData(NG_SWITCH);\n    assertArg(cases);\n    cases['?'] = transclude;\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.template = {{$route.current.template}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.children(), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.children(), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter6/recipe2/public/js/lib/angular/version.txt",
    "content": "1.0.3\n"
  },
  {
    "path": "chapter6/recipe2/public/js/services.js",
    "content": "'use strict';\n\n/* Services */\n\n\n// Demonstrate how to register services\n// In this case it is a simple value service.\nangular.module('myApp.services', []).\n  value('version', '0.1');\n"
  },
  {
    "path": "chapter6/recipe2/views/index.jade",
    "content": "extends layout\n\nblock body\n  h1 HTML5 Route Example\n  ng-view\n\n  script(src='js/lib/angular/angular.js')\n  script(src='js/lib/angular/angular-resource.js')\n  script(src='js/app.js')\n  script(src='js/services.js')\n  script(src='js/controllers.js')\n  script(src='js/filters.js')\n  script(src='js/directives.js')"
  },
  {
    "path": "chapter6/recipe2/views/layout.jade",
    "content": "!!!\nhtml(ng-app=\"myApp\")\n  head\n    meta(charset='utf8')\n    base(href='/')\n    title HTML5 Routing Example\n    link(rel='stylesheet', href='/css/bootstrap.css')\n  body\n    block body"
  },
  {
    "path": "chapter6/recipe2/views/partials/index.jade",
    "content": "p This is the index partial\nul(ng-repeat=\"person in persons\")\n  li\n    a(href=\"/persons/{{person.id}}\"){{person.name}}"
  },
  {
    "path": "chapter6/recipe2/views/partials/show.jade",
    "content": "h3 Person Details {{person.name}}\np Age: {{person.age}}\na(href=\"/persons\") Back"
  },
  {
    "path": "chapter6/recipe3/README.md",
    "content": "# angular-seed — the seed for AngularJS apps\n\nThis project is an application skeleton for a typical [AngularJS](http://angularjs.org/) web app.\nYou can use it to quickly bootstrap your angular webapp projects and dev environment for these\nprojects.\n\nThe seed contains AngularJS libraries, test libraries and a bunch of scripts all preconfigured for\ninstant web development gratification. Just clone the repo (or download the zip/tarball), start up\nour (or yours) webserver and you are ready to develop and test your application.\n\nThe seed app doesn't do much, just shows how to wire two controllers and views together. You can\ncheck it out by opening app/index.html in your browser (might not work file `file://` scheme in\ncertain browsers, see note below).\n\n_Note: While angular is client-side-only technology and it's possible to create angular webapps that\ndon't require a backend server at all, we recommend hosting the project files using a local\nwebserver during development to avoid issues with security restrictions (sandbox) in browsers. The\nsandbox implementation varies between browsers, but quite often prevents things like cookies, xhr,\netc to function properly when an html page is opened via `file://` scheme instead of `http://`._\n\n\n## How to use angular-seed\n\nClone the angular-seed repository and start hacking...\n\n\n### Running the app during development\n\nYou can pick one of these options:\n\n* serve this repository with your webserver\n* install node.js and run `scripts/web-server.js`\n\nThen navigate your browser to `http://localhost:<port>/app/index.html` to see the app running in\nyour browser.\n\n\n### Running the app in production\n\nThis really depends on how complex is your app and the overall infrastructure of your system, but\nthe general rule is that all you need in production are all the files under the `app/` directory.\nEverything else should be omitted.\n\nAngular apps are really just a bunch of static html, css and js files that just need to be hosted\nsomewhere, where they can be accessed by browsers.\n\nIf your Angular app is talking to the backend server via xhr or other means, you need to figure\nout what is the best way to host the static files to comply with the same origin policy if\napplicable. Usually this is done by hosting the files by the backend server or through\nreverse-proxying the backend server(s) and a webserver(s).\n\n\n### Running unit tests\n\nWe recommend using [jasmine](http://pivotal.github.com/jasmine/) and\n[Testacular](http://vojtajina.github.com/testacular/) for your unit tests/specs, but you are free\nto use whatever works for you.\n\nRequires [node.js](http://nodejs.org/), Testacular (`sudo npm install -g testacular`) and a local\nor remote browser.\n\n* start `scripts/test.sh` (on windows: `scripts\\test.bat`)\n  * a browser will start and connect to the Testacular server (Chrome is default browser, others can be captured by loading the same url as the one in Chrome or by changing the `config/testacular.conf.js` file)\n* to run or re-run tests just change any of your source or test javascript files\n\n\n### End to end testing\n\nAngular ships with a baked-in end-to-end test runner that understands angular, your app and allows\nyou to write your tests with jasmine-like BDD syntax.\n\nRequires a webserver, node.js + `./scripts/web-server.js` or your backend server that hosts the angular static files.\n\nCheck out the\n[end-to-end runner's documentation](http://docs.angularjs.org/guide/dev_guide.e2e-testing) for more\ninfo.\n\n* create your end-to-end tests in `test/e2e/scenarios.js`\n* serve your project directory with your http/backend server or node.js + `scripts/web-server.js`\n* to run do one of:\n  * open `http://localhost:port/test/e2e/runner.html` in your browser\n  * run the tests from console with [Testacular](vojtajina.github.com/testacular) via\n    `scripts/e2e-test.sh` or `script/e2e-test.bat`\n\n\n### Receiving updates from upstream\n\nWhen we upgrade angular-seed's repo with newer angular or testing library code, you can just\nfetch the changes and merge them into your project with git.\n\n\n## Directory Layout\n\n    app/                --> all of the files to be used in production\n      css/              --> css files\n        app.css         --> default stylesheet\n      img/              --> image files\n      index.html        --> app layout file (the main html template file of the app)\n      index-async.html  --> just like index.html, but loads js files asynchronously\n      js/               --> javascript files\n        app.js          --> application\n        controllers.js  --> application controllers\n        directives.js   --> application directives\n        filters.js      --> custom angular filters\n        services.js     --> custom angular services\n      lib/              --> angular and 3rd party javascript libraries\n        angular/\n          angular.js        --> the latest angular js\n          angular.min.js    --> the latest minified angular js\n          angular-*.js      --> angular add-on modules\n          version.txt       --> version number\n      partials/             --> angular view partials (partial html templates)\n        partial1.html\n        partial2.html\n\n    config/testacular.conf.js        --> config file for running unit tests with Testacular\n    config/testacular-e2e.conf.js    --> config file for running e2e tests with Testacular\n\n    scripts/            --> handy shell/js/ruby scripts\n      e2e-test.sh       --> runs end-to-end tests with Testacular (*nix)\n      e2e-test.bat      --> runs end-to-end tests with Testacular (windows)\n      test.bat          --> autotests unit tests with Testacular (windows)\n      test.sh           --> autotests unit tests with Testacular (*nix)\n      web-server.js     --> simple development webserver based on node.js\n\n    test/               --> test source files and libraries\n      e2e/              -->\n        runner.html     --> end-to-end test runner (open in your browser to run)\n        scenarios.js    --> end-to-end specs\n      lib/\n        angular/                --> angular testing libraries\n          angular-mocks.js      --> mocks that replace certain angular services in tests\n          angular-scenario.js   --> angular's scenario (end-to-end) test runner library\n          version.txt           --> version file\n      unit/                     --> unit level specs/tests\n        controllersSpec.js      --> specs for controllers\n        directivessSpec.js      --> specs for directives\n        filtersSpec.js          --> specs for filters\n        servicesSpec.js         --> specs for services\n\n## Contact\n\nFor more information on AngularJS please check out http://angularjs.org/\n"
  },
  {
    "path": "chapter6/recipe3/app/css/.gitignore",
    "content": ""
  },
  {
    "path": "chapter6/recipe3/app/css/app.css",
    "content": "/* app css stylesheet */\n\n.menu {\n  list-style: none;\n  border-bottom: 0.1em solid black;\n  margin-bottom: 2em;\n  padding: 0 0 0.5em;\n}\n\n.menu:before {\n  content: \"[\";\n}\n\n.menu:after {\n  content: \"]\";\n}\n\n.menu > li {\n  display: inline;\n}\n\n.menu > li.active {\n  background-color: yellow;\n}\n\n.menu > li:before {\n  content: \"|\";\n  padding-right: 0.3em;\n}\n\n.menu > li:nth-child(1):before {\n  content: \"\";\n  padding: 0;\n}\n\n"
  },
  {
    "path": "chapter6/recipe3/app/img/.gitignore",
    "content": ""
  },
  {
    "path": "chapter6/recipe3/app/index.html",
    "content": "<!doctype html>\n<html lang=\"en\" ng-app=\"MyApp\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\"/>\n</head>\n<body ng-controller=\"MainCtrl\">\n  <ul class=\"menu\">\n    <li ng-class=\"menuClass('persons')\"><a href=\"#!persons\">Home</a></li>\n    <li ng-class=\"menuClass('help')\"><a href=\"#!help\">Help</a></li>\n  </ul>\n  <h1>Routing Example</h1>\n  <ng-view></ng-view>\n  <script src=\"lib/angular/angular.js\"></script>\n  <script src=\"js/app.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "chapter6/recipe3/app/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []).\n  config(function($routeProvider, $locationProvider) {\n    $locationProvider.hashPrefix('!');\n    $routeProvider.\n      when(\"/persons\", { templateUrl: \"partials/index.html\" }).\n      when(\"/persons/:id\", { templateUrl: \"partials/show.html\", controller: \"ShowCtrl\" }).\n      when(\"/help\", { templateUrl: \"partials/help.html\" }).\n      otherwise( { redirectTo: \"/persons\" });\n});\n\napp.factory(\"Person\", function() {\n\n  var persons = [\n    { name: \"Peter\", age: 25, id: 1 },\n    { name: \"Stefan\", age: 35, id: 2 },\n    { name: \"Agnes\", age: 22, id: 3 }\n  ];\n\n  return {\n    all: function() {\n      return persons;\n    },\n    get: function(id) {\n      var result = null;\n      angular.forEach(persons, function(p) {\n        if (p.id == id) result = p;\n      });\n      return result;\n    }\n  };\n});\n\napp.controller(\"IndexCtrl\", function($scope, Person) {\n  $scope.persons = Person.all();\n});\n\napp.controller(\"ShowCtrl\", function($scope, $routeParams, Person) {\n  $scope.person = Person.get($routeParams.id);\n});\n\napp.controller(\"MainCtrl\", function($scope, $location) {\n  $scope.menuClass = function(page) {\n    var current = $location.path().substring(1);\n    return page === current ? \"active\" : \"\";\n  };\n});"
  },
  {
    "path": "chapter6/recipe3/app/lib/angular/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngCookies\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookies\n   * @requires $browser\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from\n   * this object, new cookies are created/deleted at the end of current $eval.\n   *\n   * @example\n   */\n   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for(name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            if (angular.isDefined(lastCookies[name])) {\n              cookies[name] = lastCookies[name];\n            } else {\n              delete cookies[name];\n            }\n          } else if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated){\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   * @example\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#get\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          return angular.fromJson($cookies[key]);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#put\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#remove\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter6/recipe3/app/lib/angular/angular-loader.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n\n(\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n'use strict';\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n)(window);\n\n/**\n * Closure compiler type information\n *\n * @typedef { {\n *   requires: !Array.<string>,\n *   invokeQueue: !Array.<Array.<*>>,\n *\n *   service: function(string, Function):angular.Module,\n *   factory: function(string, Function):angular.Module,\n *   value: function(string, *):angular.Module,\n *\n *   filter: function(string, Function):angular.Module,\n *\n *   init: function(Function):angular.Module\n * } }\n */\nangular.Module;\n\n"
  },
  {
    "path": "chapter6/recipe3/app/lib/angular/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g. \n *   `http://example.com:8080/api`), you'll need to escape the colon character before the port\n *   number, like this: `$resource('http://example.com\\\\:8080/api')`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` – {string} – The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` – {object=} – Optional set of pre-bound parameters for this action.\n *   - isArray – {boolean=} – If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n     * encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace((pctEncodeSpaces ? null : /%20/g), '+');\n    }\n\n    function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        action.method = angular.uppercase(action.method);\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter6/recipe3/app/lib/angular/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             '<p style=\"color:blue\">an html\\n' +\n             '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n             'snippet</p>';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n          Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n           <table>\n             <tr>\n               <td>Filter</td>\n               <td>Source</td>\n               <td>Rendered</td>\n             </tr>\n             <tr id=\"html-filter\">\n               <td>html filter</td>\n               <td>\n                 <pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre>\n               </td>\n               <td>\n                 <div ng-bind-html=\"snippet\"></div>\n               </td>\n             </tr>\n             <tr id=\"escaped-html\">\n               <td>no filter</td>\n               <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind=\"snippet\"></div></td>\n             </tr>\n             <tr id=\"html-unsafe-filter\">\n               <td>unsafe html filter</td>\n               <td><pre>&lt;div ng-bind-html-unsafe=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind-html-unsafe=\"snippet\"></div></td>\n             </tr>\n           </table>\n         </div>\n     </doc:source>\n     <doc:scenario>\n       it('should sanitize the html snippet ', function() {\n         expect(using('#html-filter').element('div').html()).\n           toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n       });\n\n       it('should escape snippet without any filter', function() {\n         expect(using('#escaped-html').element('div').html()).\n           toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n                \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n                \"snippet&lt;/p&gt;\");\n       });\n\n       it('should inline raw snippet if filtered as unsafe', function() {\n         expect(using('#html-unsafe-filter').element(\"div\").html()).\n           toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n                \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n                \"snippet</p>\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new <b>text</b>');\n         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');\n         expect(using('#escaped-html').element('div').html()).toBe(\"new &lt;b&gt;text&lt;/b&gt;\");\n         expect(using('#html-unsafe-filter').binding(\"snippet\")).toBe('new <b>text</b>');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar $sanitize = function(html) {\n  var buf = [];\n    htmlParser(html, htmlSanitizeWriter(buf));\n    return buf.join('');\n};\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP = /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  URI_REGEXP = /^((ftp|https?):\\/\\/|mailto:|#)/,\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g; // Match everything outside of normal chars and \" (quote character)\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,aside,\" +\n        \"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,\" +\n        \"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,bdi,bdo,\" +\n        \"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,\" +\n        \"span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        index = html.indexOf(\"-->\");\n\n        if ( index >= 0 ) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'), function(all, text){\n        text = text.\n          replace(COMMENT_REGEXP, \"$1\").\n          replace(CDATA_REGEXP, \"$1\");\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n\n        return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw \"Parse Error: \" + html;\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {\n      var value = doubleQuotedValue\n        || singleQoutedValue\n        || unqoutedValue\n        || '';\n\n      attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nvar hiddenPre=document.createElement(\"pre\");\nfunction decodeEntities(value) {\n  hiddenPre.innerHTML=value.replace(/</g,\"&lt;\");\n  return hiddenPre.innerText || hiddenPre.textContent || '';\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] == true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] == true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).value('$sanitize', $sanitize);\n\n/**\n * @ngdoc directive\n * @name ngSanitize.directive:ngBindHtml\n *\n * @description\n * Creates a binding that will sanitize the result of evaluating the `expression` with the\n * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n */\nangular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);\n    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {\n      value = $sanitize(value);\n      element.html(value || '');\n    });\n  };\n}]);\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n *   plain email address links.\n *\n * @param {string} text Input text.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should linkify the snippet with urls', function() {\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('Pretty text with some links:&#10;' +\n                '<a href=\"http://angularjs.org/\">http://angularjs.org/</a>,&#10;' +\n                '<a href=\"mailto:us@somewhere.org\">us@somewhere.org</a>,&#10;' +\n                '<a href=\"mailto:another@somewhere.org\">another@somewhere.org</a>,&#10;' +\n                'and one more: <a href=\"ftp://127.0.0.1/\">ftp://127.0.0.1/</a>.');\n       });\n\n       it ('should not linkify snippet without the linky filter', function() {\n         expect(using('#escaped-html').binding('snippet')).\n           toBe(\"Pretty text with some links:\\n\" +\n                \"http://angularjs.org/,\\n\" +\n                \"mailto:us@somewhere.org,\\n\" +\n                \"another@somewhere.org,\\n\" +\n                \"and one more: ftp://127.0.0.1/.\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new http://link.');\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('new <a href=\"http://link\">http://link</a>.');\n         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', function() {\n  var LINKY_URL_REGEXP = /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s\\.\\;\\,\\(\\)\\{\\}\\<\\>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    // TODO(vojta): use $sanitize instead\n    var writer = htmlSanitizeWriter(html);\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      writer.chars(raw.substr(0, i));\n      writer.start('a', {href:url});\n      writer.chars(match[0].replace(MAILTO_REGEXP, ''));\n      writer.end('a');\n      raw = raw.substring(i + match[0].length);\n    }\n    writer.chars(raw);\n    return html.join('');\n  };\n});\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter6/recipe3/app/lib/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter6/recipe3/app/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter6/recipe3/app/partials/.gitignore",
    "content": ""
  },
  {
    "path": "chapter6/recipe3/app/partials/help.html",
    "content": "<h3>Help Section</h3>\n\n<p>This is the help section</p>"
  },
  {
    "path": "chapter6/recipe3/app/partials/index.html",
    "content": "<h3>Person List</h3>\n<div ng-controller=\"IndexCtrl\">\n  <table>\n    <thead>\n      <tr>\n        <td>Name</td>\n        <td>Actions</td>\n      </tr>\n    </thead>\n    <tbody>\n      <tr ng-repeat=\"person in persons\">\n        <td>{{person.name}}</td>\n        <td><a href=\"#!persons/{{person.id}}\">Details</a></td>\n      </tr>\n    </tbody>\n  </table>\n</div>\n"
  },
  {
    "path": "chapter6/recipe3/app/partials/show.html",
    "content": "<h3>{{person.name}} Details</h3>\n<p>Name: {{person.name}}</p>\n<p>Age: {{person.age}}</p>\n\n<a href=\"#!persons\">Go back</a>"
  },
  {
    "path": "chapter6/recipe3/config/testacular-e2e.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  ANGULAR_SCENARIO,\n  ANGULAR_SCENARIO_ADAPTER,\n  'test/e2e/**/*.js'\n];\n\nautoWatch = false;\n\nbrowsers = ['Chrome'];\n\nsingleRun = true;\n\nproxies = {\n  '/': 'http://localhost:8000/'\n};\n\njunitReporter = {\n  outputFile: 'test_out/e2e.xml',\n  suite: 'e2e'\n};\n"
  },
  {
    "path": "chapter6/recipe3/config/testacular.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  JASMINE,\n  JASMINE_ADAPTER,\n  'app/lib/angular/angular.js',\n  'app/lib/angular/angular-*.js',\n  'test/lib/angular/angular-mocks.js',\n  'app/js/**/*.js',\n  'test/unit/**/*.js'\n];\n\nautoWatch = true;\n\nbrowsers = ['Chrome'];\n\njunitReporter = {\n  outputFile: 'test_out/unit.xml',\n  suite: 'unit'\n};\n"
  },
  {
    "path": "chapter6/recipe3/logs/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "chapter6/recipe3/scripts/e2e-test.bat",
    "content": "@echo off\n\nREM Windows script for running e2e tests\nREM You have to run server and capture some browser first\nREM\nREM Requirements:\nREM - NodeJS (http://nodejs.org/)\nREM - Testacular (npm install -g testacular)\n\nset BASE_DIR=%~dp0\ntestacular start \"%BASE_DIR%\\..\\config\\testacular-e2e.conf.js\" %*\n"
  },
  {
    "path": "chapter6/recipe3/scripts/e2e-test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular-e2e.conf.js $*\n"
  },
  {
    "path": "chapter6/recipe3/scripts/test.bat",
    "content": "@echo off\r\n\r\nREM Windows script for running unit tests\r\nREM You have to run server and capture some browser first\r\nREM\r\nREM Requirements:\r\nREM - NodeJS (http://nodejs.org/)\r\nREM - Testacular (npm install -g testacular)\r\n\r\nset BASE_DIR=%~dp0\r\ntestacular start \"%BASE_DIR%\\..\\config\\testacular.conf.js\" %*\r\n"
  },
  {
    "path": "chapter6/recipe3/scripts/test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular.conf.js $*\n"
  },
  {
    "path": "chapter6/recipe3/scripts/watchr.rb",
    "content": "#!/usr/bin/env watchr\n\n# config file for watchr http://github.com/mynyml/watchr\n# install: gem install watchr\n# run: watch watchr.rb\n# note: make sure that you have jstd server running (server.sh) and a browser captured\n\nlog_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log')\n\n`cd ..`\n`touch #{log_file}`\n\nputs \"String watchr... log file: #{log_file}\"\n\nwatch( '(app/js|test/unit)' )  do\n  `echo \"\\n\\ntest run started @ \\`date\\`\" > #{log_file}`\n  `scripts/test.sh &> #{log_file}`\nend\n\n"
  },
  {
    "path": "chapter6/recipe3/scripts/web-server.js",
    "content": "#!/usr/bin/env node\n\nvar util = require('util'),\n    http = require('http'),\n    fs = require('fs'),\n    url = require('url'),\n    events = require('events');\n\nvar DEFAULT_PORT = 8000;\n\nfunction main(argv) {\n  new HttpServer({\n    'GET': createServlet(StaticServlet),\n    'HEAD': createServlet(StaticServlet)\n  }).start(Number(argv[2]) || DEFAULT_PORT);\n}\n\nfunction escapeHtml(value) {\n  return value.toString().\n    replace('<', '&lt;').\n    replace('>', '&gt;').\n    replace('\"', '&quot;');\n}\n\nfunction createServlet(Class) {\n  var servlet = new Class();\n  return servlet.handleRequest.bind(servlet);\n}\n\n/**\n * An Http server implementation that uses a map of methods to decide\n * action routing.\n *\n * @param {Object} Map of method => Handler function\n */\nfunction HttpServer(handlers) {\n  this.handlers = handlers;\n  this.server = http.createServer(this.handleRequest_.bind(this));\n}\n\nHttpServer.prototype.start = function(port) {\n  this.port = port;\n  this.server.listen(port);\n  util.puts('Http Server running at http://localhost:' + port + '/');\n};\n\nHttpServer.prototype.parseUrl_ = function(urlString) {\n  var parsed = url.parse(urlString);\n  parsed.pathname = url.resolve('/', parsed.pathname);\n  return url.parse(url.format(parsed), true);\n};\n\nHttpServer.prototype.handleRequest_ = function(req, res) {\n  var logEntry = req.method + ' ' + req.url;\n  if (req.headers['user-agent']) {\n    logEntry += ' ' + req.headers['user-agent'];\n  }\n  util.puts(logEntry);\n  req.url = this.parseUrl_(req.url);\n  var handler = this.handlers[req.method];\n  if (!handler) {\n    res.writeHead(501);\n    res.end();\n  } else {\n    handler.call(this, req, res);\n  }\n};\n\n/**\n * Handles static content.\n */\nfunction StaticServlet() {}\n\nStaticServlet.MimeMap = {\n  'txt': 'text/plain',\n  'html': 'text/html',\n  'css': 'text/css',\n  'xml': 'application/xml',\n  'json': 'application/json',\n  'js': 'application/javascript',\n  'jpg': 'image/jpeg',\n  'jpeg': 'image/jpeg',\n  'gif': 'image/gif',\n  'png': 'image/png',\n  'svg': 'image/svg+xml'\n};\n\nStaticServlet.prototype.handleRequest = function(req, res) {\n  var self = this;\n  var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){\n    return String.fromCharCode(parseInt(hex, 16));\n  });\n  var parts = path.split('/');\n  if (parts[parts.length-1].charAt(0) === '.')\n    return self.sendForbidden_(req, res, path);\n  fs.stat(path, function(err, stat) {\n    if (err)\n      return self.sendMissing_(req, res, path);\n    if (stat.isDirectory())\n      return self.sendDirectory_(req, res, path);\n    return self.sendFile_(req, res, path);\n  });\n}\n\nStaticServlet.prototype.sendError_ = function(req, res, error) {\n  res.writeHead(500, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>Internal Server Error</title>\\n');\n  res.write('<h1>Internal Server Error</h1>');\n  res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');\n  util.puts('500 Internal Server Error');\n  util.puts(util.inspect(error));\n};\n\nStaticServlet.prototype.sendMissing_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(404, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>404 Not Found</title>\\n');\n  res.write('<h1>Not Found</h1>');\n  res.write(\n    '<p>The requested URL ' +\n    escapeHtml(path) +\n    ' was not found on this server.</p>'\n  );\n  res.end();\n  util.puts('404 Not Found: ' + path);\n};\n\nStaticServlet.prototype.sendForbidden_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(403, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>403 Forbidden</title>\\n');\n  res.write('<h1>Forbidden</h1>');\n  res.write(\n    '<p>You do not have permission to access ' +\n    escapeHtml(path) + ' on this server.</p>'\n  );\n  res.end();\n  util.puts('403 Forbidden: ' + path);\n};\n\nStaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {\n  res.writeHead(301, {\n      'Content-Type': 'text/html',\n      'Location': redirectUrl\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>301 Moved Permanently</title>\\n');\n  res.write('<h1>Moved Permanently</h1>');\n  res.write(\n    '<p>The document has moved <a href=\"' +\n    redirectUrl +\n    '\">here</a>.</p>'\n  );\n  res.end();\n  util.puts('301 Moved Permanently: ' + redirectUrl);\n};\n\nStaticServlet.prototype.sendFile_ = function(req, res, path) {\n  var self = this;\n  var file = fs.createReadStream(path);\n  res.writeHead(200, {\n    'Content-Type': StaticServlet.\n      MimeMap[path.split('.').pop()] || 'text/plain'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n  } else {\n    file.on('data', res.write.bind(res));\n    file.on('close', function() {\n      res.end();\n    });\n    file.on('error', function(error) {\n      self.sendError_(req, res, error);\n    });\n  }\n};\n\nStaticServlet.prototype.sendDirectory_ = function(req, res, path) {\n  var self = this;\n  if (path.match(/[^\\/]$/)) {\n    req.url.pathname += '/';\n    var redirectUrl = url.format(url.parse(url.format(req.url)));\n    return self.sendRedirect_(req, res, redirectUrl);\n  }\n  fs.readdir(path, function(err, files) {\n    if (err)\n      return self.sendError_(req, res, error);\n\n    if (!files.length)\n      return self.writeDirectoryIndex_(req, res, path, []);\n\n    var remaining = files.length;\n    files.forEach(function(fileName, index) {\n      fs.stat(path + '/' + fileName, function(err, stat) {\n        if (err)\n          return self.sendError_(req, res, err);\n        if (stat.isDirectory()) {\n          files[index] = fileName + '/';\n        }\n        if (!(--remaining))\n          return self.writeDirectoryIndex_(req, res, path, files);\n      });\n    });\n  });\n};\n\nStaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {\n  path = path.substring(1);\n  res.writeHead(200, {\n    'Content-Type': 'text/html'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n    return;\n  }\n  res.write('<!doctype html>\\n');\n  res.write('<title>' + escapeHtml(path) + '</title>\\n');\n  res.write('<style>\\n');\n  res.write('  ol { list-style-type: none; font-size: 1.2em; }\\n');\n  res.write('</style>\\n');\n  res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');\n  res.write('<ol>');\n  files.forEach(function(fileName) {\n    if (fileName.charAt(0) !== '.') {\n      res.write('<li><a href=\"' +\n        escapeHtml(fileName) + '\">' +\n        escapeHtml(fileName) + '</a></li>');\n    }\n  });\n  res.write('</ol>');\n  res.end();\n};\n\n// Must be last,\nmain(process.argv);\n"
  },
  {
    "path": "chapter6/recipe3/test/e2e/runner.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <title>End2end Test Runner</title>\n    <script src=\"../lib/angular/angular-scenario.js\" ng-autotest></script>\n    <script src=\"scenarios.js\"></script>\n  </head>\n  <body>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter6/recipe3/test/e2e/scenarios.js",
    "content": "'use strict';\n\n/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */\n\ndescribe('my app', function() {\n\n  beforeEach(function() {\n    browser().navigateTo('../../app/index.html');\n  });\n\n\n  it('should automatically redirect to /view1 when location hash/fragment is empty', function() {\n    expect(browser().location().url()).toBe(\"/view1\");\n  });\n\n\n  describe('view1', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view1');\n    });\n\n\n    it('should render view1 when user navigates to /view1', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 1/);\n    });\n\n  });\n\n\n  describe('view2', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view2');\n    });\n\n\n    it('should render view2 when user navigates to /view2', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 2/);\n    });\n\n  });\n});\n"
  },
  {
    "path": "chapter6/recipe3/test/lib/angular/angular-mocks.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n *\n * TODO(vojta): wrap whole file into closure during build\n */\n\n/**\n * @ngdoc overview\n * @name angular.mock\n * @description\n *\n * Namespace from 'angular-mocks.js' which contains testing related code.\n */\nangular.mock = {};\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ngMock.$browser\n *\n * @description\n * This service is a mock implementation of {@link ng.$browser}. It provides fake\n * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,\n * cookies, etc...\n *\n * The api of this service is the same as that of the real {@link ng.$browser $browser}, except\n * that there are several helper methods available which can be used in tests.\n */\nangular.mock.$BrowserProvider = function() {\n  this.$get = function(){\n    return new angular.mock.$Browser();\n  };\n};\n\nangular.mock.$Browser = function() {\n  var self = this;\n\n  this.isMock = true;\n  self.$$url = \"http://server/\";\n  self.$$lastUrl = self.$$url; // used by url polling fn\n  self.pollFns = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = angular.noop;\n  self.$$incOutstandingRequestCount = angular.noop;\n\n\n  // register url polling fn\n\n  self.onUrlChange = function(listener) {\n    self.pollFns.push(\n      function() {\n        if (self.$$lastUrl != self.$$url) {\n          self.$$lastUrl = self.$$url;\n          listener(self.$$url);\n        }\n      }\n    );\n\n    return listener;\n  };\n\n  self.cookieHash = {};\n  self.lastCookieHash = {};\n  self.deferredFns = [];\n  self.deferredNextId = 0;\n\n  self.defer = function(fn, delay) {\n    delay = delay || 0;\n    self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});\n    self.deferredFns.sort(function(a,b){ return a.time - b.time;});\n    return self.deferredNextId++;\n  };\n\n\n  self.defer.now = 0;\n\n\n  self.defer.cancel = function(deferId) {\n    var fnIndex;\n\n    angular.forEach(self.deferredFns, function(fn, index) {\n      if (fn.id === deferId) fnIndex = index;\n    });\n\n    if (fnIndex !== undefined) {\n      self.deferredFns.splice(fnIndex, 1);\n      return true;\n    }\n\n    return false;\n  };\n\n\n  /**\n   * @name ngMock.$browser#defer.flush\n   * @methodOf ngMock.$browser\n   *\n   * @description\n   * Flushes all pending requests and executes the defer callbacks.\n   *\n   * @param {number=} number of milliseconds to flush. See {@link #defer.now}\n   */\n  self.defer.flush = function(delay) {\n    if (angular.isDefined(delay)) {\n      self.defer.now += delay;\n    } else {\n      if (self.deferredFns.length) {\n        self.defer.now = self.deferredFns[self.deferredFns.length-1].time;\n      } else {\n        throw Error('No deferred tasks to be flushed');\n      }\n    }\n\n    while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {\n      self.deferredFns.shift().fn();\n    }\n  };\n  /**\n   * @name ngMock.$browser#defer.now\n   * @propertyOf ngMock.$browser\n   *\n   * @description\n   * Current milliseconds mock time.\n   */\n\n  self.$$baseHref = '';\n  self.baseHref = function() {\n    return this.$$baseHref;\n  };\n};\nangular.mock.$Browser.prototype = {\n\n/**\n  * @name ngMock.$browser#poll\n  * @methodOf ngMock.$browser\n  *\n  * @description\n  * run all fns in pollFns\n  */\n  poll: function poll() {\n    angular.forEach(this.pollFns, function(pollFn){\n      pollFn();\n    });\n  },\n\n  addPollFn: function(pollFn) {\n    this.pollFns.push(pollFn);\n    return pollFn;\n  },\n\n  url: function(url, replace) {\n    if (url) {\n      this.$$url = url;\n      return this;\n    }\n\n    return this.$$url;\n  },\n\n  cookies:  function(name, value) {\n    if (name) {\n      if (value == undefined) {\n        delete this.cookieHash[name];\n      } else {\n        if (angular.isString(value) &&       //strings only\n            value.length <= 4096) {          //strict cookie storage limits\n          this.cookieHash[name] = value;\n        }\n      }\n    } else {\n      if (!angular.equals(this.cookieHash, this.lastCookieHash)) {\n        this.lastCookieHash = angular.copy(this.cookieHash);\n        this.cookieHash = angular.copy(this.cookieHash);\n      }\n      return this.cookieHash;\n    }\n  },\n\n  notifyWhenNoOutstandingRequests: function(fn) {\n    fn();\n  }\n};\n\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandlerProvider\n *\n * @description\n * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed\n * into the `$exceptionHandler`.\n */\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandler\n *\n * @description\n * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed\n * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration\n * information.\n *\n *\n * <pre>\n *   describe('$exceptionHandlerProvider', function() {\n *\n *     it('should capture log messages and exceptions', function() {\n *\n *       module(function($exceptionHandlerProvider) {\n *         $exceptionHandlerProvider.mode('log');\n *       });\n *\n *       inject(function($log, $exceptionHandler, $timeout) {\n *         $timeout(function() { $log.log(1); });\n *         $timeout(function() { $log.log(2); throw 'banana peel'; });\n *         $timeout(function() { $log.log(3); });\n *         expect($exceptionHandler.errors).toEqual([]);\n *         expect($log.assertEmpty());\n *         $timeout.flush();\n *         expect($exceptionHandler.errors).toEqual(['banana peel']);\n *         expect($log.log.logs).toEqual([[1], [2], [3]]);\n *       });\n *     });\n *   });\n * </pre>\n */\n\nangular.mock.$ExceptionHandlerProvider = function() {\n  var handler;\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$exceptionHandlerProvider#mode\n   * @methodOf ngMock.$exceptionHandlerProvider\n   *\n   * @description\n   * Sets the logging mode.\n   *\n   * @param {string} mode Mode of operation, defaults to `rethrow`.\n   *\n   *   - `rethrow`: If any errors are are passed into the handler in tests, it typically\n   *                means that there is a bug in the application or test, so this mock will\n   *                make these tests fail.\n   *   - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores an\n   *            array of errors in `$exceptionHandler.errors`, to allow later assertion of them.\n   *            See {@link ngMock.$log#assertEmpty assertEmpty()} and\n   *             {@link ngMock.$log#reset reset()}\n   */\n  this.mode = function(mode) {\n    switch(mode) {\n      case 'rethrow':\n        handler = function(e) {\n          throw e;\n        };\n        break;\n      case 'log':\n        var errors = [];\n\n        handler = function(e) {\n          if (arguments.length == 1) {\n            errors.push(e);\n          } else {\n            errors.push([].slice.call(arguments, 0));\n          }\n        };\n\n        handler.errors = errors;\n        break;\n      default:\n        throw Error(\"Unknown mode '\" + mode + \"', only 'log'/'rethrow' modes are allowed!\");\n    }\n  };\n\n  this.$get = function() {\n    return handler;\n  };\n\n  this.mode('rethrow');\n};\n\n\n/**\n * @ngdoc service\n * @name ngMock.$log\n *\n * @description\n * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays\n * (one array per logging level). These arrays are exposed as `logs` property of each of the\n * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.\n *\n */\nangular.mock.$LogProvider = function() {\n\n  function concat(array1, array2, index) {\n    return array1.concat(Array.prototype.slice.call(array2, index));\n  }\n\n\n  this.$get = function () {\n    var $log = {\n      log: function() { $log.log.logs.push(concat([], arguments, 0)); },\n      warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },\n      info: function() { $log.info.logs.push(concat([], arguments, 0)); },\n      error: function() { $log.error.logs.push(concat([], arguments, 0)); }\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#reset\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Reset all of the logging arrays to empty.\n     */\n    $log.reset = function () {\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#log.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.log.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#warn.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.warn.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#info.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.info.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#error.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.error.logs = [];\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#assertEmpty\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.\n     */\n    $log.assertEmpty = function() {\n      var errors = [];\n      angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {\n        angular.forEach($log[logLevel].logs, function(log) {\n          angular.forEach(log, function (logItem) {\n            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\\n' + (logItem.stack || ''));\n          });\n        });\n      });\n      if (errors.length) {\n        errors.unshift(\"Expected $log to be empty! Either a message was logged unexpectedly, or an expected \" +\n          \"log message was not checked and removed:\");\n        errors.push('');\n        throw new Error(errors.join('\\n---------\\n'));\n      }\n    };\n\n    $log.reset();\n    return $log;\n  };\n};\n\n\n(function() {\n  var R_ISO8061_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?:\\:?(\\d\\d)(?:\\:?(\\d\\d)(?:\\.(\\d{3}))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d)))?$/;\n\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8061_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n  function int(str) {\n    return parseInt(str, 10);\n  }\n\n  function padNumber(num, digits, trim) {\n    var neg = '';\n    if (num < 0) {\n      neg =  '-';\n      num = -num;\n    }\n    num = '' + num;\n    while(num.length < digits) num = '0' + num;\n    if (trim)\n      num = num.substr(num.length - digits);\n    return neg + num;\n  }\n\n\n  /**\n   * @ngdoc object\n   * @name angular.mock.TzDate\n   * @description\n   *\n   * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.\n   *\n   * Mock of the Date type which has its timezone specified via constroctor arg.\n   *\n   * The main purpose is to create Date-like instances with timezone fixed to the specified timezone\n   * offset, so that we can test code that depends on local timezone settings without dependency on\n   * the time zone settings of the machine where the code is running.\n   *\n   * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)\n   * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*\n   *\n   * @example\n   * !!!! WARNING !!!!!\n   * This is not a complete Date object so only methods that were implemented can be called safely.\n   * To make matters worse, TzDate instances inherit stuff from Date via a prototype.\n   *\n   * We do our best to intercept calls to \"unimplemented\" methods, but since the list of methods is\n   * incomplete we might be missing some non-standard methods. This can result in errors like:\n   * \"Date.prototype.foo called on incompatible Object\".\n   *\n   * <pre>\n   * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');\n   * newYearInBratislava.getTimezoneOffset() => -60;\n   * newYearInBratislava.getFullYear() => 2010;\n   * newYearInBratislava.getMonth() => 0;\n   * newYearInBratislava.getDate() => 1;\n   * newYearInBratislava.getHours() => 0;\n   * newYearInBratislava.getMinutes() => 0;\n   * </pre>\n   *\n   */\n  angular.mock.TzDate = function (offset, timestamp) {\n    var self = new Date(0);\n    if (angular.isString(timestamp)) {\n      var tsStr = timestamp;\n\n      self.origDate = jsonStringToDate(timestamp);\n\n      timestamp = self.origDate.getTime();\n      if (isNaN(timestamp))\n        throw {\n          name: \"Illegal Argument\",\n          message: \"Arg '\" + tsStr + \"' passed into TzDate constructor is not a valid date string\"\n        };\n    } else {\n      self.origDate = new Date(timestamp);\n    }\n\n    var localOffset = new Date(timestamp).getTimezoneOffset();\n    self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;\n    self.date = new Date(timestamp + self.offsetDiff);\n\n    self.getTime = function() {\n      return self.date.getTime() - self.offsetDiff;\n    };\n\n    self.toLocaleDateString = function() {\n      return self.date.toLocaleDateString();\n    };\n\n    self.getFullYear = function() {\n      return self.date.getFullYear();\n    };\n\n    self.getMonth = function() {\n      return self.date.getMonth();\n    };\n\n    self.getDate = function() {\n      return self.date.getDate();\n    };\n\n    self.getHours = function() {\n      return self.date.getHours();\n    };\n\n    self.getMinutes = function() {\n      return self.date.getMinutes();\n    };\n\n    self.getSeconds = function() {\n      return self.date.getSeconds();\n    };\n\n    self.getTimezoneOffset = function() {\n      return offset * 60;\n    };\n\n    self.getUTCFullYear = function() {\n      return self.origDate.getUTCFullYear();\n    };\n\n    self.getUTCMonth = function() {\n      return self.origDate.getUTCMonth();\n    };\n\n    self.getUTCDate = function() {\n      return self.origDate.getUTCDate();\n    };\n\n    self.getUTCHours = function() {\n      return self.origDate.getUTCHours();\n    };\n\n    self.getUTCMinutes = function() {\n      return self.origDate.getUTCMinutes();\n    };\n\n    self.getUTCSeconds = function() {\n      return self.origDate.getUTCSeconds();\n    };\n\n    self.getUTCMilliseconds = function() {\n      return self.origDate.getUTCMilliseconds();\n    };\n\n    self.getDay = function() {\n      return self.date.getDay();\n    };\n\n    // provide this method only on browsers that already have it\n    if (self.toISOString) {\n      self.toISOString = function() {\n        return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +\n              padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +\n              padNumber(self.origDate.getUTCDate(), 2) + 'T' +\n              padNumber(self.origDate.getUTCHours(), 2) + ':' +\n              padNumber(self.origDate.getUTCMinutes(), 2) + ':' +\n              padNumber(self.origDate.getUTCSeconds(), 2) + '.' +\n              padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'\n      }\n    }\n\n    //hide all methods not implemented in this mock that the Date prototype exposes\n    var unimplementedMethods = ['getMilliseconds', 'getUTCDay',\n        'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',\n        'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',\n        'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',\n        'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',\n        'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];\n\n    angular.forEach(unimplementedMethods, function(methodName) {\n      self[methodName] = function() {\n        throw Error(\"Method '\" + methodName + \"' is not implemented in the TzDate mock\");\n      };\n    });\n\n    return self;\n  };\n\n  //make \"tzDateInstance instanceof Date\" return true\n  angular.mock.TzDate.prototype = Date.prototype;\n})();\n\n\n/**\n * @ngdoc function\n * @name angular.mock.dump\n * @description\n *\n * *NOTE*: this is not an injectable instance, just a globally available function.\n *\n * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.\n *\n * This method is also available on window, where it can be used to display objects on debug console.\n *\n * @param {*} object - any object to turn into string.\n * @return {string} a serialized string of the argument\n */\nangular.mock.dump = function(object) {\n  return serialize(object);\n\n  function serialize(object) {\n    var out;\n\n    if (angular.isElement(object)) {\n      object = angular.element(object);\n      out = angular.element('<div></div>');\n      angular.forEach(object, function(element) {\n        out.append(angular.element(element).clone());\n      });\n      out = out.html();\n    } else if (angular.isArray(object)) {\n      out = [];\n      angular.forEach(object, function(o) {\n        out.push(serialize(o));\n      });\n      out = '[ ' + out.join(', ') + ' ]';\n    } else if (angular.isObject(object)) {\n      if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {\n        out = serializeScope(object);\n      } else if (object instanceof Error) {\n        out = object.stack || ('' + object.name + ': ' + object.message);\n      } else {\n        out = angular.toJson(object, true);\n      }\n    } else {\n      out = String(object);\n    }\n\n    return out;\n  }\n\n  function serializeScope(scope, offset) {\n    offset = offset ||  '  ';\n    var log = [offset + 'Scope(' + scope.$id + '): {'];\n    for ( var key in scope ) {\n      if (scope.hasOwnProperty(key) && !key.match(/^(\\$|this)/)) {\n        log.push('  ' + key + ': ' + angular.toJson(scope[key]));\n      }\n    }\n    var child = scope.$$childHead;\n    while(child) {\n      log.push(serializeScope(child, offset + '  '));\n      child = child.$$nextSibling;\n    }\n    log.push('}');\n    return log.join('\\n' + offset);\n  }\n};\n\n/**\n * @ngdoc object\n * @name ngMock.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for unit testing application that use the\n * {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less\n * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.\n *\n * During unit testing, we want our unit tests to run quickly and have no external dependencies so\n * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or\n * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is\n * to verify whether a certain request has been sent or not, or alternatively just let the\n * application make requests, respond with pre-trained responses and assert that the end result is\n * what we expect it to be.\n *\n * This mock implementation can be used to respond with static or dynamic responses via the\n * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).\n *\n * When an Angular application needs some data from a server, it calls the $http service, which\n * sends the request to a real server using $httpBackend service. With dependency injection, it is\n * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify\n * the requests and respond with some testing data without sending a request to real server.\n *\n * There are two ways to specify what test data should be returned as http responses by the mock\n * backend when the code under test makes http requests:\n *\n * - `$httpBackend.expect` - specifies a request expectation\n * - `$httpBackend.when` - specifies a backend definition\n *\n *\n * # Request Expectations vs Backend Definitions\n *\n * Request expectations provide a way to make assertions about requests made by the application and\n * to define responses for those requests. The test will fail if the expected requests are not made\n * or they are made in the wrong order.\n *\n * Backend definitions allow you to define a fake backend for your application which doesn't assert\n * if a particular request was made or not, it just returns a trained response if a request is made.\n * The test will pass whether or not the request gets made during testing.\n *\n *\n * <table class=\"table\">\n *   <tr><th width=\"220px\"></th><th>Request expectations</th><th>Backend definitions</th></tr>\n *   <tr>\n *     <th>Syntax</th>\n *     <td>.expect(...).respond(...)</td>\n *     <td>.when(...).respond(...)</td>\n *   </tr>\n *   <tr>\n *     <th>Typical usage</th>\n *     <td>strict unit tests</td>\n *     <td>loose (black-box) unit testing</td>\n *   </tr>\n *   <tr>\n *     <th>Fulfills multiple requests</th>\n *     <td>NO</td>\n *     <td>YES</td>\n *   </tr>\n *   <tr>\n *     <th>Order of requests matters</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Request required</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Response required</th>\n *     <td>optional (see below)</td>\n *     <td>YES</td>\n *   </tr>\n * </table>\n *\n * In cases where both backend definitions and request expectations are specified during unit\n * testing, the request expectations are evaluated first.\n *\n * If a request expectation has no response specified, the algorithm will search your backend\n * definitions for an appropriate response.\n *\n * If a request didn't match any expectation or if the expectation doesn't have the response\n * defined, the backend definitions are evaluated in sequential order to see if any of them match\n * the request. The response from the first matched definition is returned.\n *\n *\n * # Flushing HTTP requests\n *\n * The $httpBackend used in production, always responds to requests with responses asynchronously.\n * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are\n * hard to write, follow and maintain. At the same time the testing mock, can't respond\n * synchronously because that would change the execution of the code under test. For this reason the\n * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending\n * requests and thus preserving the async api of the backend, while allowing the test to execute\n * synchronously.\n *\n *\n * # Unit testing with mock $httpBackend\n *\n * <pre>\n   // controller\n   function MyController($scope, $http) {\n     $http.get('/auth.py').success(function(data) {\n       $scope.user = data;\n     });\n\n     this.saveMessage = function(message) {\n       $scope.status = 'Saving...';\n       $http.post('/add-msg.py', message).success(function(response) {\n         $scope.status = '';\n       }).error(function() {\n         $scope.status = 'ERROR!';\n       });\n     };\n   }\n\n   // testing controller\n   var $httpBackend;\n\n   beforeEach(inject(function($injector) {\n     $httpBackend = $injector.get('$httpBackend');\n\n     // backend definition common for all tests\n     $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});\n   }));\n\n\n   afterEach(function() {\n     $httpBackend.verifyNoOutstandingExpectation();\n     $httpBackend.verifyNoOutstandingRequest();\n   });\n\n\n   it('should fetch authentication token', function() {\n     $httpBackend.expectGET('/auth.py');\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n   });\n\n\n   it('should send msg to server', function() {\n     // now you don’t care about the authentication, but\n     // the controller will still send the request and\n     // $httpBackend will respond without you having to\n     // specify the expectation and response for this request\n     $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');\n\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n     controller.saveMessage('message content');\n     expect(controller.status).toBe('Saving...');\n     $httpBackend.flush();\n     expect(controller.status).toBe('');\n   });\n\n\n   it('should send auth header', function() {\n     $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {\n       // check if the header was send, if it wasn't the expectation won't\n       // match the request and the test will fail\n       return headers['Authorization'] == 'xxx';\n     }).respond(201, '');\n\n     var controller = scope.$new(MyController);\n     controller.saveMessage('whatever');\n     $httpBackend.flush();\n   });\n   </pre>\n */\nangular.mock.$HttpBackendProvider = function() {\n  this.$get = [createHttpBackendMock];\n};\n\n/**\n * General factory function for $httpBackend mock.\n * Returns instance for unit testing (when no arguments specified):\n *   - passing through is disabled\n *   - auto flushing is disabled\n *\n * Returns instance for e2e testing (when `$delegate` and `$browser` specified):\n *   - passing through (delegating request to real backend) is enabled\n *   - auto flushing is enabled\n *\n * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)\n * @param {Object=} $browser Auto-flushing enabled if specified\n * @return {Object} Instance of $httpBackend mock\n */\nfunction createHttpBackendMock($delegate, $browser) {\n  var definitions = [],\n      expectations = [],\n      responses = [],\n      responsesPush = angular.bind(responses, responses.push);\n\n  function createResponse(status, data, headers) {\n    if (angular.isFunction(status)) return status;\n\n    return function() {\n      return angular.isNumber(status)\n          ? [status, data, headers]\n          : [200, status, data];\n    };\n  }\n\n  // TODO(vojta): change params to: method, url, data, headers, callback\n  function $httpBackend(method, url, data, callback, headers) {\n    var xhr = new MockXhr(),\n        expectation = expectations[0],\n        wasExpected = false;\n\n    function prettyPrint(data) {\n      return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)\n          ? data\n          : angular.toJson(data);\n    }\n\n    if (expectation && expectation.match(method, url)) {\n      if (!expectation.matchData(data))\n        throw Error('Expected ' + expectation + ' with different data\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.data) + '\\nGOT:      ' + data);\n\n      if (!expectation.matchHeaders(headers))\n        throw Error('Expected ' + expectation + ' with different headers\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.headers) + '\\nGOT:      ' +\n            prettyPrint(headers));\n\n      expectations.shift();\n\n      if (expectation.response) {\n        responses.push(function() {\n          var response = expectation.response(method, url, data, headers);\n          xhr.$$respHeaders = response[2];\n          callback(response[0], response[1], xhr.getAllResponseHeaders());\n        });\n        return;\n      }\n      wasExpected = true;\n    }\n\n    var i = -1, definition;\n    while ((definition = definitions[++i])) {\n      if (definition.match(method, url, data, headers || {})) {\n        if (definition.response) {\n          // if $browser specified, we do auto flush all requests\n          ($browser ? $browser.defer : responsesPush)(function() {\n            var response = definition.response(method, url, data, headers);\n            xhr.$$respHeaders = response[2];\n            callback(response[0], response[1], xhr.getAllResponseHeaders());\n          });\n        } else if (definition.passThrough) {\n          $delegate(method, url, data, callback, headers);\n        } else throw Error('No response defined !');\n        return;\n      }\n    }\n    throw wasExpected ?\n        Error('No response defined !') :\n        Error('Unexpected request: ' + method + ' ' + url + '\\n' +\n              (expectation ? 'Expected ' + expectation : 'No more request expected'));\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#when\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current definition.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.when = function(method, url, data, headers) {\n    var definition = new MockHttpExpectation(method, url, data, headers),\n        chain = {\n          respond: function(status, data, headers) {\n            definition.response = createResponse(status, data, headers);\n          }\n        };\n\n    if ($browser) {\n      chain.passThrough = function() {\n        definition.passThrough = true;\n      };\n    }\n\n    definitions.push(definition);\n    return chain;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for GET requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for HEAD requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for DELETE requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for POST requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for PUT requests.  For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for JSONP requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n  createShortMethods('when');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expect\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current expectation.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *  request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.expect = function(method, url, data, headers) {\n    var expectation = new MockHttpExpectation(method, url, data, headers);\n    expectations.push(expectation);\n    return {\n      respond: function(status, data, headers) {\n        expectation.response = createResponse(status, data, headers);\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for GET requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled. See #expect for more info.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for HEAD requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for DELETE requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for POST requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PUT requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPATCH\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PATCH requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for JSONP requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n  createShortMethods('expect');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#flush\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Flushes all pending requests using the trained responses.\n   *\n   * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,\n   *   all pending requests will be flushed. If there are no pending requests when the flush method\n   *   is called an exception is thrown (as this typically a sign of programming error).\n   */\n  $httpBackend.flush = function(count) {\n    if (!responses.length) throw Error('No pending request to flush !');\n\n    if (angular.isDefined(count)) {\n      while (count--) {\n        if (!responses.length) throw Error('No more pending request to flush !');\n        responses.shift()();\n      }\n    } else {\n      while (responses.length) {\n        responses.shift()();\n      }\n    }\n    $httpBackend.verifyNoOutstandingExpectation();\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingExpectation\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that all of the requests defined via the `expect` api were made. If any of the\n   * requests were not made, verifyNoOutstandingExpectation throws an exception.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyExpectations);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingExpectation = function() {\n    if (expectations.length) {\n      throw Error('Unsatisfied requests: ' + expectations.join(', '));\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingRequest\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that there are no outstanding requests that need to be flushed.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyNoOutstandingRequest);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingRequest = function() {\n    if (responses.length) {\n      throw Error('Unflushed requests: ' + responses.length);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#resetExpectations\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Resets all request expectations, but preserves all backend definitions. Typically, you would\n   * call resetExpectations during a multiple-phase test when you want to reuse the same instance of\n   * $httpBackend mock.\n   */\n  $httpBackend.resetExpectations = function() {\n    expectations.length = 0;\n    responses.length = 0;\n  };\n\n  return $httpBackend;\n\n\n  function createShortMethods(prefix) {\n    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {\n     $httpBackend[prefix + method] = function(url, headers) {\n       return $httpBackend[prefix](method, url, undefined, headers)\n     }\n    });\n\n    angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {\n      $httpBackend[prefix + method] = function(url, data, headers) {\n        return $httpBackend[prefix](method, url, data, headers)\n      }\n    });\n  }\n}\n\nfunction MockHttpExpectation(method, url, data, headers) {\n\n  this.data = data;\n  this.headers = headers;\n\n  this.match = function(m, u, d, h) {\n    if (method != m) return false;\n    if (!this.matchUrl(u)) return false;\n    if (angular.isDefined(d) && !this.matchData(d)) return false;\n    if (angular.isDefined(h) && !this.matchHeaders(h)) return false;\n    return true;\n  };\n\n  this.matchUrl = function(u) {\n    if (!url) return true;\n    if (angular.isFunction(url.test)) return url.test(u);\n    return url == u;\n  };\n\n  this.matchHeaders = function(h) {\n    if (angular.isUndefined(headers)) return true;\n    if (angular.isFunction(headers)) return headers(h);\n    return angular.equals(headers, h);\n  };\n\n  this.matchData = function(d) {\n    if (angular.isUndefined(data)) return true;\n    if (data && angular.isFunction(data.test)) return data.test(d);\n    if (data && !angular.isString(data)) return angular.toJson(data) == d;\n    return data == d;\n  };\n\n  this.toString = function() {\n    return method + ' ' + url;\n  };\n}\n\nfunction MockXhr() {\n\n  // hack for testing $http, $httpBackend\n  MockXhr.$$lastInstance = this;\n\n  this.open = function(method, url, async) {\n    this.$$method = method;\n    this.$$url = url;\n    this.$$async = async;\n    this.$$reqHeaders = {};\n    this.$$respHeaders = {};\n  };\n\n  this.send = function(data) {\n    this.$$data = data;\n  };\n\n  this.setRequestHeader = function(key, value) {\n    this.$$reqHeaders[key] = value;\n  };\n\n  this.getResponseHeader = function(name) {\n    // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last\n    var header = this.$$respHeaders[name];\n    if (header) return header;\n\n    name = angular.lowercase(name);\n    header = this.$$respHeaders[name];\n    if (header) return header;\n\n    header = undefined;\n    angular.forEach(this.$$respHeaders, function(headerVal, headerName) {\n      if (!header && angular.lowercase(headerName) == name) header = headerVal;\n    });\n    return header;\n  };\n\n  this.getAllResponseHeaders = function() {\n    var lines = [];\n\n    angular.forEach(this.$$respHeaders, function(value, key) {\n      lines.push(key + ': ' + value);\n    });\n    return lines.join('\\n');\n  };\n\n  this.abort = angular.noop;\n}\n\n\n/**\n * @ngdoc function\n * @name ngMock.$timeout\n * @description\n *\n * This service is just a simple decorator for {@link ng.$timeout $timeout} service\n * that adds a \"flush\" method.\n */\n\n/**\n * @ngdoc method\n * @name ngMock.$timeout#flush\n * @methodOf ngMock.$timeout\n * @description\n *\n * Flushes the queue of pending tasks.\n */\n\n/**\n *\n */\nangular.mock.$RootElementProvider = function() {\n  this.$get = function() {\n    return angular.element('<div ng-app></div>');\n  }\n};\n\n/**\n * @ngdoc overview\n * @name ngMock\n * @description\n *\n * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful\n * mocks to the {@link AUTO.$injector $injector}.\n */\nangular.module('ngMock', ['ng']).provider({\n  $browser: angular.mock.$BrowserProvider,\n  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,\n  $log: angular.mock.$LogProvider,\n  $httpBackend: angular.mock.$HttpBackendProvider,\n  $rootElement: angular.mock.$RootElementProvider\n}).config(function($provide) {\n  $provide.decorator('$timeout', function($delegate, $browser) {\n    $delegate.flush = function() {\n      $browser.defer.flush();\n    };\n    return $delegate;\n  });\n});\n\n\n/**\n * @ngdoc overview\n * @name ngMockE2E\n * @description\n *\n * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.\n * Currently there is only one mock present in this module -\n * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.\n */\nangular.module('ngMockE2E', ['ng']).config(function($provide) {\n  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);\n});\n\n/**\n * @ngdoc object\n * @name ngMockE2E.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of\n * applications that use the {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for unit testing please see\n * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.\n *\n * This implementation can be used to respond with static or dynamic responses via the `when` api\n * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the\n * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch\n * templates from a webserver).\n *\n * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application\n * is being developed with the real backend api replaced with a mock, it is often desirable for\n * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch\n * templates or static files from the webserver). To configure the backend with this behavior\n * use the `passThrough` request handler of `when` instead of `respond`.\n *\n * Additionally, we don't want to manually have to flush mocked out requests like we do during unit\n * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests\n * automatically, closely simulating the behavior of the XMLHttpRequest object.\n *\n * To setup the application to run with this http backend, you have to create a module that depends\n * on the `ngMockE2E` and your application modules and defines the fake backend:\n *\n * <pre>\n *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);\n *   myAppDev.run(function($httpBackend) {\n *     phones = [{name: 'phone1'}, {name: 'phone2'}];\n *\n *     // returns the current list of phones\n *     $httpBackend.whenGET('/phones').respond(phones);\n *\n *     // adds a new phone to the phones array\n *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {\n *       phones.push(angular.fromJSON(data));\n *     });\n *     $httpBackend.whenGET(/^\\/templates\\//).passThrough();\n *     //...\n *   });\n * </pre>\n *\n * Afterwards, bootstrap your app with this new module.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#when\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition.\n *\n * @param {string} method HTTP method.\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n *   object and returns true if the headers match the current definition.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n *\n *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n *    – The respond method takes a set of static data to be returned or a function that can return\n *    an array containing response status (number), response data (string) and response headers\n *    (Object).\n *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`\n *    handler, will be pass through to the real backend (an XHR request will be made to the\n *    server.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenGET\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for GET requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenHEAD\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for HEAD requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenDELETE\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for DELETE requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPOST\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for POST requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPUT\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PUT requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPATCH\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PATCH requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenJSONP\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for JSONP requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\nangular.mock.e2e = {};\nangular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];\n\n\nangular.mock.clearDataCache = function() {\n  var key,\n      cache = angular.element.cache;\n\n  for(key in cache) {\n    if (cache.hasOwnProperty(key)) {\n      var handle = cache[key].handle;\n\n      handle && angular.element(handle.elem).unbind();\n      delete cache[key];\n    }\n  }\n};\n\n\nwindow.jstestdriver && (function(window) {\n  /**\n   * Global method to output any number of objects into JSTD console. Useful for debugging.\n   */\n  window.dump = function() {\n    var args = [];\n    angular.forEach(arguments, function(arg) {\n      args.push(angular.mock.dump(arg));\n    });\n    jstestdriver.console.log.apply(jstestdriver.console, args);\n    if (window.console) {\n      window.console.log.apply(window.console, args);\n    }\n  };\n})(window);\n\n\nwindow.jasmine && (function(window) {\n\n  afterEach(function() {\n    var spec = getCurrentSpec();\n    var injector = spec.$injector;\n\n    spec.$injector = null;\n    spec.$modules = null;\n\n    if (injector) {\n      injector.get('$rootElement').unbind();\n      injector.get('$browser').pollFns.length = 0;\n    }\n\n    angular.mock.clearDataCache();\n\n    // clean up jquery's fragment cache\n    angular.forEach(angular.element.fragments, function(val, key) {\n      delete angular.element.fragments[key];\n    });\n\n    MockXhr.$$lastInstance = null;\n\n    angular.forEach(angular.callbacks, function(val, key) {\n      delete angular.callbacks[key];\n    });\n    angular.callbacks.counter = 0;\n  });\n\n  function getCurrentSpec() {\n    return jasmine.getEnv().currentSpec;\n  }\n\n  function isSpecRunning() {\n    var spec = getCurrentSpec();\n    return spec && spec.queue.running;\n  }\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.module\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * This function registers a module configuration code. It collects the configuration information\n   * which will be used when the injector is created by {@link angular.mock.inject inject}.\n   *\n   * See {@link angular.mock.inject inject} for usage example\n   *\n   * @param {...(string|Function)} fns any number of modules which are represented as string\n   *        aliases or as anonymous module initialization functions. The modules are used to\n   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.\n   */\n  window.module = angular.mock.module = function() {\n    var moduleFns = Array.prototype.slice.call(arguments, 0);\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      if (spec.$injector) {\n        throw Error('Injector already created, can not register a module!');\n      } else {\n        var modules = spec.$modules || (spec.$modules = []);\n        angular.forEach(moduleFns, function(module) {\n          modules.push(module);\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.inject\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * The inject function wraps a function into an injectable function. The inject() creates new\n   * instance of {@link AUTO.$injector $injector} per test, which is then used for\n   * resolving references.\n   *\n   * See also {@link angular.mock.module module}\n   *\n   * Example of what a typical jasmine tests looks like with the inject method.\n   * <pre>\n   *\n   *   angular.module('myApplicationModule', [])\n   *       .value('mode', 'app')\n   *       .value('version', 'v1.0.1');\n   *\n   *\n   *   describe('MyApp', function() {\n   *\n   *     // You need to load modules that you want to test,\n   *     // it loads only the \"ng\" module by default.\n   *     beforeEach(module('myApplicationModule'));\n   *\n   *\n   *     // inject() is used to inject arguments of all given functions\n   *     it('should provide a version', inject(function(mode, version) {\n   *       expect(version).toEqual('v1.0.1');\n   *       expect(mode).toEqual('app');\n   *     }));\n   *\n   *\n   *     // The inject and module method can also be used inside of the it or beforeEach\n   *     it('should override a version and test the new version is injected', function() {\n   *       // module() takes functions or strings (module aliases)\n   *       module(function($provide) {\n   *         $provide.value('version', 'overridden'); // override version here\n   *       });\n   *\n   *       inject(function(version) {\n   *         expect(version).toEqual('overridden');\n   *       });\n   *     ));\n   *   });\n   *\n   * </pre>\n   *\n   * @param {...Function} fns any number of functions which will be injected using the injector.\n   */\n  window.inject = angular.mock.inject = function() {\n    var blockFns = Array.prototype.slice.call(arguments, 0);\n    var errorForStack = new Error('Declaration Location');\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      var modules = spec.$modules || [];\n      modules.unshift('ngMock');\n      modules.unshift('ng');\n      var injector = spec.$injector;\n      if (!injector) {\n        injector = spec.$injector = angular.injector(modules);\n      }\n      for(var i = 0, ii = blockFns.length; i < ii; i++) {\n        try {\n          injector.invoke(blockFns[i] || angular.noop, this);\n        } catch (e) {\n          if(e.stack) e.stack +=  '\\n' + errorForStack.stack;\n          throw e;\n        } finally {\n          errorForStack = null;\n        }\n      }\n    }\n  };\n})(window);\n"
  },
  {
    "path": "chapter6/recipe3/test/lib/angular/angular-scenario.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Mar 21 12:46:34 2012 -0700\n */\n(function( window, undefined ) {\n'use strict';\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.7.2\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in array && array[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n\t\tvar exec,\n\t\t\tbulk = key == null,\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\n\t\t// Sets many values\n\t\tif ( key && typeof key === \"object\" ) {\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n\t\t\t}\n\t\t\tchainable = 1;\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = pass === undefined && jQuery.isFunction( value );\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations only iterate when executing function values\n\t\t\t\tif ( exec ) {\n\t\t\t\t\texec = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn exec.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\n\t\t\t\t// Otherwise they run against the entire set\n\t\t\t\t} else {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor (; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchainable = 1;\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfired = true;\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar length = list.length;\n\t\t\t\t\tadd( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory || memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tfragment,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tpixelMargin: true\n\t};\n\n\t// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead\n\tjQuery.boxModel = support.boxModel = (document.compatMode === \"CSS1Compat\");\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor ( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\tfragment.removeChild( div );\n\n\t// Null elements to avoid leaks in IE\n\tfragment = select = opt = div = input = null;\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tmarginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,\n\t\t\tpaddingMarginBorderVisibility, paddingMarginBorder,\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tconMarginTop = 1;\n\t\tpaddingMarginBorder = \"padding:0;margin:0;border:\";\n\t\tpositionTopLeftWidthHeight = \"position:absolute;top:0;left:0;width:1px;height:1px;\";\n\t\tpaddingMarginBorderVisibility = paddingMarginBorder + \"0;visibility:hidden;\";\n\t\tstyle = \"style='\" + positionTopLeftWidthHeight + paddingMarginBorder + \"5px solid #000;\";\n\t\thtml = \"<div \" + style + \"display:block;'><div style='\" + paddingMarginBorder + \"0;display:block;overflow:hidden;'></div></div>\" +\n\t\t\t\"<table \" + style + \"' cellpadding='0' cellspacing='0'>\" +\n\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = paddingMarginBorderVisibility + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td style='\" + paddingMarginBorder + \"0;display:none'></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName( \"td\" );\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t// gets computed margin-right based on width of container. For more\n\t\t// info see bug #3333\n\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tmarginDiv = document.createElement( \"div\" );\n\t\t\tmarginDiv.style.width = \"0\";\n\t\t\tmarginDiv.style.marginRight = \"0\";\n\t\t\tdiv.style.width = \"2px\";\n\t\t\tdiv.appendChild( marginDiv );\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\t// (IE < 8 does this)\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.width = div.style.padding = \"1px\";\n\t\t\tdiv.style.border = 0;\n\t\t\tdiv.style.overflow = \"hidden\";\n\t\t\tdiv.style.display = \"inline\";\n\t\t\tdiv.style.zoom = 1;\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.style.overflow = \"visible\";\n\t\t\tdiv.innerHTML = \"<div style='width:5px;'></div>\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\t\t}\n\n\t\tdiv.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;\n\t\tdiv.innerHTML = html;\n\n\t\touter = div.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.style.marginTop = \"1%\";\n\t\t\tsupport.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== \"1%\";\n\t\t}\n\n\t\tif ( typeof container.style.zoom !== \"undefined\" ) {\n\t\t\tcontainer.style.zoom = 1;\n\t\t}\n\n\t\tbody.removeChild( container );\n\t\tmarginDiv = div = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\treturn support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ internalKey ] : internalKey;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ internalKey ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( internalKey );\n\t\t\t} else {\n\t\t\t\telem[ internalKey ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, part, attr, name, l,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = elem.attributes;\n\t\t\t\t\tfor ( l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split( \".\", 2 );\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\t\tpart = parts[1] + \"!\";\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\tdata = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\tif ( data === undefined && elem ) {\n\t\t\t\t\tdata = jQuery.data( elem, key );\n\t\t\t\t\tdata = dataAttr( elem, key, data );\n\t\t\t\t}\n\n\t\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\t\tdata;\n\t\t\t}\n\n\t\t\tparts[1] = value;\n\t\t\tthis.each(function() {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.triggerHandler( \"setData\" + part, parts );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + part, parts );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, false );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\thooks = {};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( object );\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, l, isBool,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\t\t\tattrNames = value.toLowerCase().split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tisBool = rboolean.test( name );\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\t// Do not do this for boolean attributes (see #10870)\n\t\t\t\t\tif ( !isBool ) {\n\t\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\t}\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( isBool && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true,\n\t\tcoords: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = \"\" + value );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+)?\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\tvar attrs = elem.attributes || {};\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || (attrs.id || {}).value === m[2]) &&\n\t\t\t(!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tquick: selector && quickParse( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t ( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\told = null;\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\tspecial = jQuery.event.special[ event.type ] || {},\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n\t\t\t// Pregenerate a single jQuery object for reuse with .is()\n\t\t\tjqcur = jQuery(this);\n\t\t\tjqcur.context = this.ownerDocument || this;\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process events on disabled elements (#6911, #8165)\n\t\t\t\tif ( cur.disabled !== true ) {\n\t\t\t\t\tselMatch = {};\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tjqcur[0] = cur;\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\t\tselMatch[ sel ] = (\n\t\t\t\t\t\t\t\thandleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\tret;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\t\t\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\telem._change_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) { // && selector != null\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( var type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\n\t\t\tparts.push( m[1] );\n\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\t\t/* falls through */\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n// Expose origPOS\n// \"global\" as in regardless of relation to brackets/parens\nExpr.match.globalPOS = origPOS;\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry {\n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.globalPOS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\tPOS.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery.clean(arguments) );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tnull;\n\t\t\t}\n\n\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, function( i, elem ) {\n\t\t\t\t\tif ( elem.src ) {\n\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\turl: elem.src,\n\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\tdataType: \"script\"\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\n\t// IE blanks contents when cloning scripts\n\t} else if ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdest.text = src.text;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n\n\t// Clear flags for bubbling special change/submit events, they must\n\t// be reattached when the newly cloned events are first activated\n\tdest.removeAttribute( \"_submit_attached\" );\n\tdest.removeAttribute( \"_change_attached\" );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n\t// Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n\tvar div = document.createElement( \"div\" );\n\tsafeFragment.appendChild( div );\n\n\tdiv.innerHTML = elem.outerHTML;\n\treturn div.firstChild;\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t\tclone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ?\n\t\t\t\telem.cloneNode( true ) :\n\t\t\t\tshimCloneNode( elem );\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType, script, j,\n\t\t\t\tret = [];\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\"),\n\t\t\t\t\t\tsafeChildNodes = safeFragment.childNodes,\n\t\t\t\t\t\tremove;\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\n\t\t\t\t\t// Clear elements from DocumentFragment (safeFragment or otherwise)\n\t\t\t\t\t// to avoid hoarding elements. Fixes #11356\n\t\t\t\t\tif ( div ) {\n\t\t\t\t\t\tdiv.parentNode.removeChild( div );\n\n\t\t\t\t\t\t// Guard against -1 index exceptions in FF3.6\n\t\t\t\t\t\tif ( safeChildNodes.length > 0 ) {\n\t\t\t\t\t\t\tremove = safeChildNodes[ safeChildNodes.length - 1 ];\n\n\t\t\t\t\t\t\tif ( remove && remove.parentNode ) {\n\t\t\t\t\t\t\t\tremove.parentNode.removeChild( remove );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tscript = ret[i];\n\t\t\t\tif ( scripts && jQuery.nodeName( script, \"script\" ) && (!script.type || rscriptType.test( script.type )) ) {\n\t\t\t\t\tscripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( script.nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( script.getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( script );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnum = /^[\\-+]?(?:\\d*\\.)?\\d+$/i,\n\trnumnonpx = /^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\trmargin = /^margin/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\n\t// order is important!\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\treturn jQuery.access( this, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t}, name, value, arguments.length > 1 );\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {},\n\t\t\tret, name;\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// DEPRECATED in 1.3, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle, width,\n\t\t\tstyle = elem.style;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( (defaultView = elem.ownerDocument.defaultView) &&\n\t\t\t\t(computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// WebKit uses \"computed value (percentage if specified)\" instead of \"used value\" for margins\n\t\t// which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {\n\t\t\twidth = style.width;\n\t\t\tstyle.width = ret;\n\t\t\tret = computedStyle.width;\n\t\t\tstyle.width = width;\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( rnumnonpx.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\ti = name === \"width\" ? 1 : 0,\n\t\tlen = 4;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tfor ( ; i < len; i += 2 ) {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ];\n\t}\n\n\t// Computed unit is not pixels. Stop here and return.\n\tif ( rnumnonpx.test(val) ) {\n\t\treturn val;\n\t}\n\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tfor ( ; i < len; i += 2 ) {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val + \"px\";\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\treturn jQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\treturn rnum.test( value ) ?\n\t\t\t\tvalue + \"px\" :\n\t\t\t\tvalue;\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\treturn curCSS( elem, \"margin-right\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i,\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n\t\t\t\texpanded = {};\n\n\t\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n});\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = ( typeof s.data === \"string\" ) && /^application\\/x\\-www\\-form\\-urlencoded/.test( s.contentType );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t} catch( _ ) {\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( (display === \"\" && jQuery.css(elem, \"display\") === \"none\") ||\n\t\t\t\t\t\t!jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e, hooks, replace,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\t// first pass over propertys to expand / normalize\n\t\t\tfor ( p in prop ) {\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tif ( ( hooks = jQuery.cssHooks[ name ] ) && \"expand\" in hooks ) {\n\t\t\t\t\treplace = hooks.expand( prop[ name ] );\n\t\t\t\t\tdelete prop[ name ];\n\n\t\t\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t\t\t// also - reusing 'p' from above because we have the correct \"name\"\n\t\t\t\t\tfor ( p in replace ) {\n\t\t\t\t\t\tif ( ! ( p in prop ) ) {\n\t\t\t\t\t\t\tprop[ p ] = replace[ p ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( name in prop ) {\n\t\t\t\tval = prop[ name ];\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, index ) {\n\t\t\t\tvar hooks = data[ index ];\n\t\t\t\tjQuery.removeData( elem, index, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n\t\t\t\tstopQueue( this, data, index );\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ index ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ index ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p ) {\n\t\t\treturn p;\n\t\t},\n\t\tswing: function( p ) {\n\t\t\treturn ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tif ( self.options.hide ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t\t} else if ( self.options.show ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.end );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Ensure props that can't be negative don't go there on undershoot easing\njQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {\n\t// exclude marginTop, marginLeft, marginBottom and marginRight from this list\n\tif ( prop.indexOf( \"margin\" ) ) {\n\t\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( jQuery.support.boxModel ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar getOffset,\n\trtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tgetOffset = function( elem, doc, docElem, box ) {\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow( doc ),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tgetOffset = function( elem, doc, docElem ) {\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar elem = this[0],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn null;\n\t}\n\n\tif ( elem === doc.body ) {\n\t\treturn jQuery.offset.bodyOffset( elem );\n\t}\n\n\treturn getOffset( elem, doc, doc.documentElement );\n};\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t top ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tvar clientProp = \"client\" + name,\n\t\tscrollProp = \"scroll\" + name,\n\t\toffsetProp = \"offset\" + name;\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( value ) {\n\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\tvar doc, docElemProp, orig, ret;\n\n\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\t\tdoc = elem.document;\n\t\t\t\tdocElemProp = doc.documentElement[ clientProp ];\n\t\t\t\treturn jQuery.support.boxModel && docElemProp ||\n\t\t\t\t\tdoc.body && doc.body[ clientProp ] || docElemProp;\n\t\t\t}\n\n\t\t\t// Get document width or height\n\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t// when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]\n\t\t\t\t// so we can't use max, as it'll choose the incorrect offset[Width/Height]\n\t\t\t\t// instead we use the correct client[Width/Height]\n\t\t\t\t// support:IE6\n\t\t\t\tif ( doc[ clientProp ] >= doc[ scrollProp ] ) {\n\t\t\t\t\treturn doc[ clientProp ];\n\t\t\t\t}\n\n\t\t\t\treturn Math.max(\n\t\t\t\t\telem.body[ scrollProp ], doc[ scrollProp ],\n\t\t\t\t\telem.body[ offsetProp ], doc[ offsetProp ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get width or height on the element\n\t\t\tif ( value === undefined ) {\n\t\t\t\torig = jQuery.css( elem, type );\n\t\t\t\tret = parseFloat( orig );\n\t\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\t\t\t}\n\n\t\t\t// Set the width or height on the element\n\t\t\tjQuery( elem ).css( type, value );\n\t\t}, type, value, arguments.length, null );\n\t};\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );\n/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document){\n  var _jQuery = window.jQuery.noConflict(true);\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n\n/**\n * Setup file for the Scenario.\n * Must be first in the compilation/bootstrap list.\n */\n\n// Public namespace\nangular.scenario = angular.scenario || {};\n\n/**\n * Defines a new output format.\n *\n * @param {string} name the name of the new output format\n * @param {function()} fn function(context, runner) that generates the output\n */\nangular.scenario.output = angular.scenario.output || function(name, fn) {\n  angular.scenario.output[name] = fn;\n};\n\n/**\n * Defines a new DSL statement. If your factory function returns a Future\n * it's returned, otherwise the result is assumed to be a map of functions\n * for chaining. Chained functions are subject to the same rules.\n *\n * Note: All functions on the chain are bound to the chain scope so values\n *   set on \"this\" in your statement function are available in the chained\n *   functions.\n *\n * @param {string} name The name of the statement\n * @param {function()} fn Factory function(), return a function for\n *  the statement.\n */\nangular.scenario.dsl = angular.scenario.dsl || function(name, fn) {\n  angular.scenario.dsl[name] = function() {\n    function executeStatement(statement, args) {\n      var result = statement.apply(this, args);\n      if (angular.isFunction(result) || result instanceof angular.scenario.Future)\n        return result;\n      var self = this;\n      var chain = angular.extend({}, result);\n      angular.forEach(chain, function(value, name) {\n        if (angular.isFunction(value)) {\n          chain[name] = function() {\n            return executeStatement.call(self, value, arguments);\n          };\n        } else {\n          chain[name] = value;\n        }\n      });\n      return chain;\n    }\n    var statement = fn.apply(this, arguments);\n    return function() {\n      return executeStatement.call(this, statement, arguments);\n    };\n  };\n};\n\n/**\n * Defines a new matcher for use with the expects() statement. The value\n * this.actual (like in Jasmine) is available in your matcher to compare\n * against. Your function should return a boolean. The future is automatically\n * created for you.\n *\n * @param {string} name The name of the matcher\n * @param {function()} fn The matching function(expected).\n */\nangular.scenario.matcher = angular.scenario.matcher || function(name, fn) {\n  angular.scenario.matcher[name] = function(expected) {\n    var prefix = 'expect ' + this.future.name + ' ';\n    if (this.inverse) {\n      prefix += 'not ';\n    }\n    var self = this;\n    this.addFuture(prefix + name + ' ' + angular.toJson(expected),\n      function(done) {\n        var error;\n        self.actual = self.future.value;\n        if ((self.inverse && fn.call(self, expected)) ||\n            (!self.inverse && !fn.call(self, expected))) {\n          error = 'expected ' + angular.toJson(expected) +\n            ' but was ' + angular.toJson(self.actual);\n        }\n        done(error);\n    });\n  };\n};\n\n/**\n * Initialize the scenario runner and run !\n *\n * Access global window and document object\n * Access $runner through closure\n *\n * @param {Object=} config Config options\n */\nangular.scenario.setUpAndRun = function(config) {\n  var href = window.location.href;\n  var body = _jQuery(document.body);\n  var output = [];\n  var objModel = new angular.scenario.ObjectModel($runner);\n\n  if (config && config.scenario_output) {\n    output = config.scenario_output.split(',');\n  }\n\n  angular.forEach(angular.scenario.output, function(fn, name) {\n    if (!output.length || indexOf(output,name) != -1) {\n      var context = body.append('<div></div>').find('div:last');\n      context.attr('id', name);\n      fn.call({}, context, $runner, objModel);\n    }\n  });\n\n  if (!/^http/.test(href) && !/^https/.test(href)) {\n    body.append('<p id=\"system-error\"></p>');\n    body.find('#system-error').text(\n      'Scenario runner must be run using http or https. The protocol ' +\n      href.split(':')[0] + ':// is not supported.'\n    );\n    return;\n  }\n\n  var appFrame = body.append('<div id=\"application\"></div>').find('#application');\n  var application = new angular.scenario.Application(appFrame);\n\n  $runner.on('RunnerEnd', function() {\n    appFrame.css('display', 'none');\n    appFrame.find('iframe').attr('src', 'about:blank');\n  });\n\n  $runner.on('RunnerError', function(error) {\n    if (window.console) {\n      console.log(formatException(error));\n    } else {\n      // Do something for IE\n      alert(error);\n    }\n  });\n\n  $runner.run(application);\n};\n\n/**\n * Iterates through list with iterator function that must call the\n * continueFunction to continute iterating.\n *\n * @param {Array} list list to iterate over\n * @param {function()} iterator Callback function(value, continueFunction)\n * @param {function()} done Callback function(error, result) called when\n *   iteration finishes or an error occurs.\n */\nfunction asyncForEach(list, iterator, done) {\n  var i = 0;\n  function loop(error, index) {\n    if (index && index > i) {\n      i = index;\n    }\n    if (error || i >= list.length) {\n      done(error);\n    } else {\n      try {\n        iterator(list[i++], loop);\n      } catch (e) {\n        done(e);\n      }\n    }\n  }\n  loop();\n}\n\n/**\n * Formats an exception into a string with the stack trace, but limits\n * to a specific line length.\n *\n * @param {Object} error The exception to format, can be anything throwable\n * @param {Number=} [maxStackLines=5] max lines of the stack trace to include\n *  default is 5.\n */\nfunction formatException(error, maxStackLines) {\n  maxStackLines = maxStackLines || 5;\n  var message = error.toString();\n  if (error.stack) {\n    var stack = error.stack.split('\\n');\n    if (stack[0].indexOf(message) === -1) {\n      maxStackLines++;\n      stack.unshift(error.message);\n    }\n    message = stack.slice(0, maxStackLines).join('\\n');\n  }\n  return message;\n}\n\n/**\n * Returns a function that gets the file name and line number from a\n * location in the stack if available based on the call site.\n *\n * Note: this returns another function because accessing .stack is very\n * expensive in Chrome.\n *\n * @param {Number} offset Number of stack lines to skip\n */\nfunction callerFile(offset) {\n  var error = new Error();\n\n  return function() {\n    var line = (error.stack || '').split('\\n')[offset];\n\n    // Clean up the stack trace line\n    if (line) {\n      if (line.indexOf('@') !== -1) {\n        // Firefox\n        line = line.substring(line.indexOf('@')+1);\n      } else {\n        // Chrome\n        line = line.substring(line.indexOf('(')+1).replace(')', '');\n      }\n    }\n\n    return line || '';\n  };\n}\n\n/**\n * Triggers a browser event. Attempts to choose the right event if one is\n * not specified.\n *\n * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement\n * @param {string} type Optional event type.\n * @param {Array.<string>=} keys Optional list of pressed keys\n *        (valid values: 'alt', 'meta', 'shift', 'ctrl')\n */\nfunction browserTrigger(element, type, keys) {\n  if (element && !element.nodeName) element = element[0];\n  if (!element) return;\n  if (!type) {\n    type = {\n        'text':            'change',\n        'textarea':        'change',\n        'hidden':          'change',\n        'password':        'change',\n        'button':          'click',\n        'submit':          'click',\n        'reset':           'click',\n        'image':           'click',\n        'checkbox':        'click',\n        'radio':           'click',\n        'select-one':      'change',\n        'select-multiple': 'change'\n    }[lowercase(element.type)] || 'click';\n  }\n  if (lowercase(nodeName_(element)) == 'option') {\n    element.parentNode.value = element.value;\n    element = element.parentNode;\n    type = 'change';\n  }\n\n  keys = keys || [];\n  function pressed(key) {\n    return indexOf(keys, key) !== -1;\n  }\n\n  if (msie < 9) {\n    switch(element.type) {\n      case 'radio':\n      case 'checkbox':\n        element.checked = !element.checked;\n        break;\n    }\n    // WTF!!! Error: Unspecified error.\n    // Don't know why, but some elements when detached seem to be in inconsistent state and\n    // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)\n    // forcing the browser to compute the element position (by reading its CSS)\n    // puts the element in consistent state.\n    element.style.posLeft;\n\n    // TODO(vojta): create event objects with pressed keys to get it working on IE<9\n    var ret = element.fireEvent('on' + type);\n    if (lowercase(element.type) == 'submit') {\n      while(element) {\n        if (lowercase(element.nodeName) == 'form') {\n          element.fireEvent('onsubmit');\n          break;\n        }\n        element = element.parentNode;\n      }\n    }\n    return ret;\n  } else {\n    var evnt = document.createEvent('MouseEvents'),\n        originalPreventDefault = evnt.preventDefault,\n        iframe = _jQuery('#application iframe')[0],\n        appWindow = iframe ? iframe.contentWindow : window,\n        fakeProcessDefault = true,\n        finalProcessDefault,\n        angular = appWindow.angular || {};\n\n    // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208\n    angular['ff-684208-preventDefault'] = false;\n    evnt.preventDefault = function() {\n      fakeProcessDefault = false;\n      return originalPreventDefault.apply(evnt, arguments);\n    };\n\n    evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, pressed('ctrl'), pressed('alt'),\n                        pressed('shift'), pressed('meta'), 0, element);\n\n    element.dispatchEvent(evnt);\n    finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);\n\n    delete angular['ff-684208-preventDefault'];\n\n    return finalProcessDefault;\n  }\n}\n\n/**\n * Don't use the jQuery trigger method since it works incorrectly.\n *\n * jQuery notifies listeners and then changes the state of a checkbox and\n * does not create a real browser event. A real click changes the state of\n * the checkbox and then notifies listeners.\n *\n * To work around this we instead use our own handler that fires a real event.\n */\n(function(fn){\n  var parentTrigger = fn.trigger;\n  fn.trigger = function(type) {\n    if (/(click|change|keydown|blur|input)/.test(type)) {\n      var processDefaults = [];\n      this.each(function(index, node) {\n        processDefaults.push(browserTrigger(node, type));\n      });\n\n      // this is not compatible with jQuery - we return an array of returned values,\n      // so that scenario runner know whether JS code has preventDefault() of the event or not...\n      return processDefaults;\n    }\n    return parentTrigger.apply(this, arguments);\n  };\n})(_jQuery.fn);\n\n/**\n * Finds all bindings with the substring match of name and returns an\n * array of their values.\n *\n * @param {string} bindExp The name to match\n * @return {Array.<string>} String of binding values\n */\n_jQuery.fn.bindings = function(windowJquery, bindExp) {\n  var result = [], match,\n      bindSelector = '.ng-binding:visible';\n  if (angular.isString(bindExp)) {\n    bindExp = bindExp.replace(/\\s/g, '');\n    match = function (actualExp) {\n      if (actualExp) {\n        actualExp = actualExp.replace(/\\s/g, '');\n        if (actualExp == bindExp) return true;\n        if (actualExp.indexOf(bindExp) == 0) {\n          return actualExp.charAt(bindExp.length) == '|';\n        }\n      }\n    }\n  } else if (bindExp) {\n    match = function(actualExp) {\n      return actualExp && bindExp.exec(actualExp);\n    }\n  } else {\n    match = function(actualExp) {\n      return !!actualExp;\n    };\n  }\n  var selection = this.find(bindSelector);\n  if (this.is(bindSelector)) {\n    selection = selection.add(this);\n  }\n\n  function push(value) {\n    if (value == undefined) {\n      value = '';\n    } else if (typeof value != 'string') {\n      value = angular.toJson(value);\n    }\n    result.push('' + value);\n  }\n\n  selection.each(function() {\n    var element = windowJquery(this),\n        binding;\n    if (binding = element.data('$binding')) {\n      if (typeof binding == 'string') {\n        if (match(binding)) {\n          push(element.scope().$eval(binding));\n        }\n      } else {\n        if (!angular.isArray(binding)) {\n          binding = [binding];\n        }\n        for(var fns, j=0, jj=binding.length;  j<jj; j++) {\n          fns = binding[j];\n          if (fns.parts) {\n            fns = fns.parts;\n          } else {\n            fns = [fns];\n          }\n          for (var scope, fn, i = 0, ii = fns.length; i < ii; i++) {\n            if(match((fn = fns[i]).exp)) {\n              push(fn(scope = scope || element.scope()));\n            }\n          }\n        }\n      }\n    }\n  });\n  return result;\n};\n\n/**\n * Represents the application currently being tested and abstracts usage\n * of iframes or separate windows.\n *\n * @param {Object} context jQuery wrapper around HTML context.\n */\nangular.scenario.Application = function(context) {\n  this.context = context;\n  context.append(\n    '<h2>Current URL: <a href=\"about:blank\">None</a></h2>' +\n    '<div id=\"test-frames\"></div>'\n  );\n};\n\n/**\n * Gets the jQuery collection of frames. Don't use this directly because\n * frames may go stale.\n *\n * @private\n * @return {Object} jQuery collection\n */\nangular.scenario.Application.prototype.getFrame_ = function() {\n  return this.context.find('#test-frames iframe:last');\n};\n\n/**\n * Gets the window of the test runner frame. Always favor executeAction()\n * instead of this method since it prevents you from getting a stale window.\n *\n * @private\n * @return {Object} the window of the frame\n */\nangular.scenario.Application.prototype.getWindow_ = function() {\n  var contentWindow = this.getFrame_().prop('contentWindow');\n  if (!contentWindow)\n    throw 'Frame window is not accessible.';\n  return contentWindow;\n};\n\n/**\n * Changes the location of the frame.\n *\n * @param {string} url The URL. If it begins with a # then only the\n *   hash of the page is changed.\n * @param {function()} loadFn function($window, $document) Called when frame loads.\n * @param {function()} errorFn function(error) Called if any error when loading.\n */\nangular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorFn) {\n  var self = this;\n  var frame = this.getFrame_();\n  //TODO(esprehn): Refactor to use rethrow()\n  errorFn = errorFn || function(e) { throw e; };\n  if (url === 'about:blank') {\n    errorFn('Sandbox Error: Navigating to about:blank is not allowed.');\n  } else if (url.charAt(0) === '#') {\n    url = frame.attr('src').split('#')[0] + url;\n    frame.attr('src', url);\n    this.executeAction(loadFn);\n  } else {\n    frame.remove();\n    this.context.find('#test-frames').append('<iframe>');\n    frame = this.getFrame_();\n    frame.load(function() {\n      frame.unbind();\n      try {\n        self.executeAction(loadFn);\n      } catch (e) {\n        errorFn(e);\n      }\n    }).attr('src', url);\n  }\n  this.context.find('> h2 a').attr('href', url).text(url);\n};\n\n/**\n * Executes a function in the context of the tested application. Will wait\n * for all pending angular xhr requests before executing.\n *\n * @param {function()} action The callback to execute. function($window, $document)\n *  $document is a jQuery wrapped document.\n */\nangular.scenario.Application.prototype.executeAction = function(action) {\n  var self = this;\n  var $window = this.getWindow_();\n  if (!$window.document) {\n    throw 'Sandbox Error: Application document not accessible.';\n  }\n  if (!$window.angular) {\n    return action.call(this, $window, _jQuery($window.document));\n  }\n  angularInit($window.document, function(element) {\n    var $injector = $window.angular.element(element).injector();\n    var $element = _jQuery(element);\n\n    $element.injector = function() {\n      return $injector;\n    };\n\n    $injector.invoke(function($browser){\n      $browser.notifyWhenNoOutstandingRequests(function() {\n        action.call(self, $window, $element);\n      });\n    });\n  });\n};\n\n/**\n * The representation of define blocks. Don't used directly, instead use\n * define() in your tests.\n *\n * @param {string} descName Name of the block\n * @param {Object} parent describe or undefined if the root.\n */\nangular.scenario.Describe = function(descName, parent) {\n  this.only = parent && parent.only;\n  this.beforeEachFns = [];\n  this.afterEachFns = [];\n  this.its = [];\n  this.children = [];\n  this.name = descName;\n  this.parent = parent;\n  this.id = angular.scenario.Describe.id++;\n\n  /**\n   * Calls all before functions.\n   */\n  var beforeEachFns = this.beforeEachFns;\n  this.setupBefore = function() {\n    if (parent) parent.setupBefore.call(this);\n    angular.forEach(beforeEachFns, function(fn) { fn.call(this); }, this);\n  };\n\n  /**\n   * Calls all after functions.\n   */\n  var afterEachFns = this.afterEachFns;\n  this.setupAfter  = function() {\n    angular.forEach(afterEachFns, function(fn) { fn.call(this); }, this);\n    if (parent) parent.setupAfter.call(this);\n  };\n};\n\n// Shared Unique ID generator for every describe block\nangular.scenario.Describe.id = 0;\n\n// Shared Unique ID generator for every it (spec)\nangular.scenario.Describe.specId = 0;\n\n/**\n * Defines a block to execute before each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.beforeEach = function(body) {\n  this.beforeEachFns.push(body);\n};\n\n/**\n * Defines a block to execute after each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.afterEach = function(body) {\n  this.afterEachFns.push(body);\n};\n\n/**\n * Creates a new describe block that's a child of this one.\n *\n * @param {string} name Name of the block. Appended to the parent block's name.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.describe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Same as describe() but makes ddescribe blocks the only to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.ddescribe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  child.only = true;\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Use to disable a describe block.\n */\nangular.scenario.Describe.prototype.xdescribe = angular.noop;\n\n/**\n * Defines a test.\n *\n * @param {string} name Name of the test.\n * @param {function()} vody Body of the block.\n */\nangular.scenario.Describe.prototype.it = function(name, body) {\n  this.its.push({\n    id: angular.scenario.Describe.specId++,\n    definition: this,\n    only: this.only,\n    name: name,\n    before: this.setupBefore,\n    body: body,\n    after: this.setupAfter\n  });\n};\n\n/**\n * Same as it() but makes iit tests the only test to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.iit = function(name, body) {\n  this.it.apply(this, arguments);\n  this.its[this.its.length-1].only = true;\n};\n\n/**\n * Use to disable a test block.\n */\nangular.scenario.Describe.prototype.xit = angular.noop;\n\n/**\n * Gets an array of functions representing all the tests (recursively).\n * that can be executed with SpecRunner's.\n *\n * @return {Array<Object>} Array of it blocks {\n *   definition : Object // parent Describe\n *   only: boolean\n *   name: string\n *   before: Function\n *   body: Function\n *   after: Function\n *  }\n */\nangular.scenario.Describe.prototype.getSpecs = function() {\n  var specs = arguments[0] || [];\n  angular.forEach(this.children, function(child) {\n    child.getSpecs(specs);\n  });\n  angular.forEach(this.its, function(it) {\n    specs.push(it);\n  });\n  var only = [];\n  angular.forEach(specs, function(it) {\n    if (it.only) {\n      only.push(it);\n    }\n  });\n  return (only.length && only) || specs;\n};\n\n/**\n * A future action in a spec.\n *\n * @param {string} name of the future action\n * @param {function()} future callback(error, result)\n * @param {function()} Optional. function that returns the file/line number.\n */\nangular.scenario.Future = function(name, behavior, line) {\n  this.name = name;\n  this.behavior = behavior;\n  this.fulfilled = false;\n  this.value = undefined;\n  this.parser = angular.identity;\n  this.line = line || function() { return ''; };\n};\n\n/**\n * Executes the behavior of the closure.\n *\n * @param {function()} doneFn Callback function(error, result)\n */\nangular.scenario.Future.prototype.execute = function(doneFn) {\n  var self = this;\n  this.behavior(function(error, result) {\n    self.fulfilled = true;\n    if (result) {\n      try {\n        result = self.parser(result);\n      } catch(e) {\n        error = e;\n      }\n    }\n    self.value = error || result;\n    doneFn(error, result);\n  });\n};\n\n/**\n * Configures the future to convert it's final with a function fn(value)\n *\n * @param {function()} fn function(value) that returns the parsed value\n */\nangular.scenario.Future.prototype.parsedWith = function(fn) {\n  this.parser = fn;\n  return this;\n};\n\n/**\n * Configures the future to parse it's final value from JSON\n * into objects.\n */\nangular.scenario.Future.prototype.fromJson = function() {\n  return this.parsedWith(angular.fromJson);\n};\n\n/**\n * Configures the future to convert it's final value from objects\n * into JSON.\n */\nangular.scenario.Future.prototype.toJson = function() {\n  return this.parsedWith(angular.toJson);\n};\n\n/**\n * Maintains an object tree from the runner events.\n *\n * @param {Object} runner The scenario Runner instance to connect to.\n *\n * TODO(esprehn): Every output type creates one of these, but we probably\n *  want one global shared instance. Need to handle events better too\n *  so the HTML output doesn't need to do spec model.getSpec(spec.id)\n *  silliness.\n *\n * TODO(vojta) refactor on, emit methods (from all objects) - use inheritance\n */\nangular.scenario.ObjectModel = function(runner) {\n  var self = this;\n\n  this.specMap = {};\n  this.listeners = [];\n  this.value = {\n    name: '',\n    children: {}\n  };\n\n  runner.on('SpecBegin', function(spec) {\n    var block = self.value,\n        definitions = [];\n\n    angular.forEach(self.getDefinitionPath(spec), function(def) {\n      if (!block.children[def.name]) {\n        block.children[def.name] = {\n          id: def.id,\n          name: def.name,\n          children: {},\n          specs: {}\n        };\n      }\n      block = block.children[def.name];\n      definitions.push(def.name);\n    });\n\n    var it = self.specMap[spec.id] =\n             block.specs[spec.name] =\n             new angular.scenario.ObjectModel.Spec(spec.id, spec.name, definitions);\n\n    // forward the event\n    self.emit('SpecBegin', it);\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var it = self.getSpec(spec.id);\n    it.status = 'error';\n    it.error = error;\n\n    // forward the event\n    self.emit('SpecError', it, error);\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    complete(it);\n\n    // forward the event\n    self.emit('SpecEnd', it);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var it = self.getSpec(spec.id);\n    var step = new angular.scenario.ObjectModel.Step(step.name);\n    it.steps.push(step);\n\n    // forward the event\n    self.emit('StepBegin', it, step);\n  });\n\n  runner.on('StepEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    var step = it.getLastStep();\n    if (step.name !== step.name)\n      throw 'Events fired in the wrong order. Step names don\\'t match.';\n    complete(step);\n\n    // forward the event\n    self.emit('StepEnd', it, step);\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('failure', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepFailure', it, modelStep, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('error', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepError', it, modelStep, error);\n  });\n\n  runner.on('RunnerBegin', function() {\n    self.emit('RunnerBegin');\n  });\n  runner.on('RunnerEnd', function() {\n    self.emit('RunnerEnd');\n  });\n\n  function complete(item) {\n    item.endTime = new Date().getTime();\n    item.duration = item.endTime - item.startTime;\n    item.status = item.status || 'success';\n  }\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName Name of the event to add a handler for\n * @param {function()} listener Function that will be called when event is fired\n */\nangular.scenario.ObjectModel.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.ObjectModel.prototype.emit = function(eventName) {\n  var self = this,\n      args = Array.prototype.slice.call(arguments, 1),\n      eventName = eventName.toLowerCase();\n\n  if (this.listeners[eventName]) {\n    angular.forEach(this.listeners[eventName], function(listener) {\n      listener.apply(self, args);\n    });\n  }\n};\n\n/**\n * Computes the path of definition describe blocks that wrap around\n * this spec.\n *\n * @param spec Spec to compute the path for.\n * @return {Array<Describe>} The describe block path\n */\nangular.scenario.ObjectModel.prototype.getDefinitionPath = function(spec) {\n  var path = [];\n  var currentDefinition = spec.definition;\n  while (currentDefinition && currentDefinition.name) {\n    path.unshift(currentDefinition);\n    currentDefinition = currentDefinition.parent;\n  }\n  return path;\n};\n\n/**\n * Gets a spec by id.\n *\n * @param {string} The id of the spec to get the object for.\n * @return {Object} the Spec instance\n */\nangular.scenario.ObjectModel.prototype.getSpec = function(id) {\n  return this.specMap[id];\n};\n\n/**\n * A single it block.\n *\n * @param {string} id Id of the spec\n * @param {string} name Name of the spec\n * @param {Array<string>=} definitionNames List of all describe block names that wrap this spec\n */\nangular.scenario.ObjectModel.Spec = function(id, name, definitionNames) {\n  this.id = id;\n  this.name = name;\n  this.startTime = new Date().getTime();\n  this.steps = [];\n  this.fullDefinitionName = (definitionNames || []).join(' ');\n};\n\n/**\n * Adds a new step to the Spec.\n *\n * @param {string} step Name of the step (really name of the future)\n * @return {Object} the added step\n */\nangular.scenario.ObjectModel.Spec.prototype.addStep = function(name) {\n  var step = new angular.scenario.ObjectModel.Step(name);\n  this.steps.push(step);\n  return step;\n};\n\n/**\n * Gets the most recent step.\n *\n * @return {Object} the step\n */\nangular.scenario.ObjectModel.Spec.prototype.getLastStep = function() {\n  return this.steps[this.steps.length-1];\n};\n\n/**\n * Set status of the Spec from given Step\n *\n * @param {angular.scenario.ObjectModel.Step} step\n */\nangular.scenario.ObjectModel.Spec.prototype.setStatusFromStep = function(step) {\n  if (!this.status || step.status == 'error') {\n    this.status = step.status;\n    this.error = step.error;\n    this.line = step.line;\n  }\n};\n\n/**\n * A single step inside a Spec.\n *\n * @param {string} step Name of the step\n */\nangular.scenario.ObjectModel.Step = function(name) {\n  this.name = name;\n  this.startTime = new Date().getTime();\n};\n\n/**\n * Helper method for setting all error status related properties\n *\n * @param {string} status\n * @param {string} error\n * @param {string} line\n */\nangular.scenario.ObjectModel.Step.prototype.setErrorStatus = function(status, error, line) {\n  this.status = status;\n  this.error = error;\n  this.line = line;\n};\n\n/**\n * Runner for scenarios\n *\n * Has to be initialized before any test is loaded,\n * because it publishes the API into window (global space).\n */\nangular.scenario.Runner = function($window) {\n  this.listeners = [];\n  this.$window = $window;\n  this.rootDescribe = new angular.scenario.Describe();\n  this.currentDescribe = this.rootDescribe;\n  this.api = {\n    it: this.it,\n    iit: this.iit,\n    xit: angular.noop,\n    describe: this.describe,\n    ddescribe: this.ddescribe,\n    xdescribe: angular.noop,\n    beforeEach: this.beforeEach,\n    afterEach: this.afterEach\n  };\n  angular.forEach(this.api, angular.bind(this, function(fn, key) {\n    this.$window[key] = angular.bind(this, fn);\n  }));\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.Runner.prototype.emit = function(eventName) {\n  var self = this;\n  var args = Array.prototype.slice.call(arguments, 1);\n  eventName = eventName.toLowerCase();\n  if (!this.listeners[eventName])\n    return;\n  angular.forEach(this.listeners[eventName], function(listener) {\n    listener.apply(self, args);\n  });\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName The name of the event to add a handler for\n * @param {string} listener The fn(...) that takes the extra arguments from emit()\n */\nangular.scenario.Runner.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Defines a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.describe = function(name, body) {\n  var self = this;\n  this.currentDescribe.describe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Same as describe, but makes ddescribe the only blocks to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.ddescribe = function(name, body) {\n  var self = this;\n  this.currentDescribe.ddescribe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Defines a test in a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.it = function(name, body) {\n  this.currentDescribe.it(name, body);\n};\n\n/**\n * Same as it, but makes iit tests the only tests to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.iit = function(name, body) {\n  this.currentDescribe.iit(name, body);\n};\n\n/**\n * Defines a function to be called before each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.beforeEach = function(body) {\n  this.currentDescribe.beforeEach(body);\n};\n\n/**\n * Defines a function to be called after each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.afterEach = function(body) {\n  this.currentDescribe.afterEach(body);\n};\n\n/**\n * Creates a new spec runner.\n *\n * @private\n * @param {Object} scope parent scope\n */\nangular.scenario.Runner.prototype.createSpecRunner_ = function(scope) {\n  var child = scope.$new();\n  var Cls = angular.scenario.SpecRunner;\n\n  // Export all the methods to child scope manually as now we don't mess controllers with scopes\n  // TODO(vojta): refactor scenario runner so that these objects are not tightly coupled as current\n  for (var name in Cls.prototype)\n    child[name] = angular.bind(child, Cls.prototype[name]);\n\n  Cls.call(child);\n  return child;\n};\n\n/**\n * Runs all the loaded tests with the specified runner class on the\n * provided application.\n *\n * @param {angular.scenario.Application} application App to remote control.\n */\nangular.scenario.Runner.prototype.run = function(application) {\n  var self = this;\n  var $root = angular.injector(['ng']).get('$rootScope');\n  angular.extend($root, this);\n  angular.forEach(angular.scenario.Runner.prototype, function(fn, name) {\n    $root[name] = angular.bind(self, fn);\n  });\n  $root.application = application;\n  $root.emit('RunnerBegin');\n  asyncForEach(this.rootDescribe.getSpecs(), function(spec, specDone) {\n    var dslCache = {};\n    var runner = self.createSpecRunner_($root);\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      dslCache[key] = fn.call($root);\n    });\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      self.$window[key] = function() {\n        var line = callerFile(3);\n        var scope = runner.$new();\n\n        // Make the dsl accessible on the current chain\n        scope.dsl = {};\n        angular.forEach(dslCache, function(fn, key) {\n          scope.dsl[key] = function() {\n            return dslCache[key].apply(scope, arguments);\n          };\n        });\n\n        // Make these methods work on the current chain\n        scope.addFuture = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFuture.apply(scope, arguments);\n        };\n        scope.addFutureAction = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFutureAction.apply(scope, arguments);\n        };\n\n        return scope.dsl[key].apply(scope, arguments);\n      };\n    });\n    runner.run(spec, function() {\n      runner.$destroy();\n      specDone.apply(this, arguments);\n    });\n  },\n  function(error) {\n    if (error) {\n      self.emit('RunnerError', error);\n    }\n    self.emit('RunnerEnd');\n  });\n};\n\n/**\n * This class is the \"this\" of the it/beforeEach/afterEach method.\n * Responsibilities:\n *   - \"this\" for it/beforeEach/afterEach\n *   - keep state for single it/beforeEach/afterEach execution\n *   - keep track of all of the futures to execute\n *   - run single spec (execute each future)\n */\nangular.scenario.SpecRunner = function() {\n  this.futures = [];\n  this.afterIndex = 0;\n};\n\n/**\n * Executes a spec which is an it block with associated before/after functions\n * based on the describe nesting.\n *\n * @param {Object} spec A spec object\n * @param {function()} specDone function that is called when the spec finshes. Function(error, index)\n */\nangular.scenario.SpecRunner.prototype.run = function(spec, specDone) {\n  var self = this;\n  this.spec = spec;\n\n  this.emit('SpecBegin', spec);\n\n  try {\n    spec.before.call(this);\n    spec.body.call(this);\n    this.afterIndex = this.futures.length;\n    spec.after.call(this);\n  } catch (e) {\n    this.emit('SpecError', spec, e);\n    this.emit('SpecEnd', spec);\n    specDone();\n    return;\n  }\n\n  var handleError = function(error, done) {\n    if (self.error) {\n      return done();\n    }\n    self.error = true;\n    done(null, self.afterIndex);\n  };\n\n  asyncForEach(\n    this.futures,\n    function(future, futureDone) {\n      self.step = future;\n      self.emit('StepBegin', spec, future);\n      try {\n        future.execute(function(error) {\n          if (error) {\n            self.emit('StepFailure', spec, future, error);\n            self.emit('StepEnd', spec, future);\n            return handleError(error, futureDone);\n          }\n          self.emit('StepEnd', spec, future);\n          self.$window.setTimeout(function() { futureDone(); }, 0);\n        });\n      } catch (e) {\n        self.emit('StepError', spec, future, e);\n        self.emit('StepEnd', spec, future);\n        handleError(e, futureDone);\n      }\n    },\n    function(e) {\n      if (e) {\n        self.emit('SpecError', spec, e);\n      }\n      self.emit('SpecEnd', spec);\n      // Call done in a timeout so exceptions don't recursively\n      // call this function\n      self.$window.setTimeout(function() { specDone(); }, 0);\n    }\n  );\n};\n\n/**\n * Adds a new future action.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFuture = function(name, behavior, line) {\n  var future = new angular.scenario.Future(name, angular.bind(this, behavior), line);\n  this.futures.push(future);\n  return future;\n};\n\n/**\n * Adds a new future action to be executed on the application window.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior, line) {\n  var self = this;\n  var NG = /\\[ng\\\\\\:/;\n  return this.addFuture(name, function(done) {\n    this.application.executeAction(function($window, $document) {\n\n      //TODO(esprehn): Refactor this so it doesn't need to be in here.\n      $document.elements = function(selector) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        selector = (self.selector || '') + ' ' + (selector || '');\n        selector = _jQuery.trim(selector) || '*';\n        angular.forEach(args, function(value, index) {\n          selector = selector.replace('$' + (index + 1), value);\n        });\n        var result = $document.find(selector);\n        if (selector.match(NG)) {\n          angular.forEach(['[ng-','[data-ng-','[x-ng-'], function(value, index){\n            result = result.add(selector.replace(NG, value), $document);\n          });\n        }\n        if (!result.length) {\n          throw {\n            type: 'selector',\n            message: 'Selector ' + selector + ' did not match any elements.'\n          };\n        }\n\n        return result;\n      };\n\n      try {\n        behavior.call(self, $window, $document, done);\n      } catch(e) {\n        if (e.type && e.type === 'selector') {\n          done(e.message);\n        } else {\n          throw e;\n        }\n      }\n    });\n  }, line);\n};\n\n/**\n * Shared DSL statements that are useful to all scenarios.\n */\n\n /**\n * Usage:\n *    pause() pauses until you call resume() in the console\n */\nangular.scenario.dsl('pause', function() {\n  return function() {\n    return this.addFuture('pausing for you to resume', function(done) {\n      this.emit('InteractivePause', this.spec, this.step);\n      this.$window.resume = function() { done(); };\n    });\n  };\n});\n\n/**\n * Usage:\n *    sleep(seconds) pauses the test for specified number of seconds\n */\nangular.scenario.dsl('sleep', function() {\n  return function(time) {\n    return this.addFuture('sleep for ' + time + ' seconds', function(done) {\n      this.$window.setTimeout(function() { done(null, time * 1000); }, time * 1000);\n    });\n  };\n});\n\n/**\n * Usage:\n *    browser().navigateTo(url) Loads the url into the frame\n *    browser().navigateTo(url, fn) where fn(url) is called and returns the URL to navigate to\n *    browser().reload() refresh the page (reload the same URL)\n *    browser().window.href() window.location.href\n *    browser().window.path() window.location.pathname\n *    browser().window.search() window.location.search\n *    browser().window.hash() window.location.hash without # prefix\n *    browser().location().url() see ng.$location#url\n *    browser().location().path() see ng.$location#path\n *    browser().location().search() see ng.$location#search\n *    browser().location().hash() see ng.$location#hash\n */\nangular.scenario.dsl('browser', function() {\n  var chain = {};\n\n  chain.navigateTo = function(url, delegate) {\n    var application = this.application;\n    return this.addFuture(\"browser navigate to '\" + url + \"'\", function(done) {\n      if (delegate) {\n        url = delegate.call(this, url);\n      }\n      application.navigateTo(url, function() {\n        done(null, url);\n      }, done);\n    });\n  };\n\n  chain.reload = function() {\n    var application = this.application;\n    return this.addFutureAction('browser reload', function($window, $document, done) {\n      var href = $window.location.href;\n      application.navigateTo(href, function() {\n        done(null, href);\n      }, done);\n    });\n  };\n\n  chain.window = function() {\n    var api = {};\n\n    api.href = function() {\n      return this.addFutureAction('window.location.href', function($window, $document, done) {\n        done(null, $window.location.href);\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('window.location.path', function($window, $document, done) {\n        done(null, $window.location.pathname);\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('window.location.search', function($window, $document, done) {\n        done(null, $window.location.search);\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('window.location.hash', function($window, $document, done) {\n        done(null, $window.location.hash.replace('#', ''));\n      });\n    };\n\n    return api;\n  };\n\n  chain.location = function() {\n    var api = {};\n\n    api.url = function() {\n      return this.addFutureAction('$location.url()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').url());\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('$location.path()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').path());\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('$location.search()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').search());\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('$location.hash()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').hash());\n      });\n    };\n\n    return api;\n  };\n\n  return function() {\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    expect(future).{matcher} where matcher is one of the matchers defined\n *    with angular.scenario.matcher\n *\n * ex. expect(binding(\"name\")).toEqual(\"Elliott\")\n */\nangular.scenario.dsl('expect', function() {\n  var chain = angular.extend({}, angular.scenario.matcher);\n\n  chain.not = function() {\n    this.inverse = true;\n    return chain;\n  };\n\n  return function(future) {\n    this.future = future;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    using(selector, label) scopes the next DSL element selection\n *\n * ex.\n *   using('#foo', \"'Foo' text field\").input('bar')\n */\nangular.scenario.dsl('using', function() {\n  return function(selector, label) {\n    this.selector = _jQuery.trim((this.selector||'') + ' ' + selector);\n    if (angular.isString(label) && label.length) {\n      this.label = label + ' ( ' + this.selector + ' )';\n    } else {\n      this.label = this.selector;\n    }\n    return this.dsl;\n  };\n});\n\n/**\n * Usage:\n *    binding(name) returns the value of the first matching binding\n */\nangular.scenario.dsl('binding', function() {\n  return function(name) {\n    return this.addFutureAction(\"select binding '\" + name + \"'\", function($window, $document, done) {\n      var values = $document.elements().bindings($window.angular.element, name);\n      if (!values.length) {\n        return done(\"Binding selector '\" + name + \"' did not match.\");\n      }\n      done(null, values[0]);\n    });\n  };\n});\n\n/**\n * Usage:\n *    input(name).enter(value) enters value in input with specified name\n *    input(name).check() checks checkbox\n *    input(name).select(value) selects the radio button with specified name/value\n *    input(name).val() returns the value of the input.\n */\nangular.scenario.dsl('input', function() {\n  var chain = {};\n  var supportInputEvent =  'oninput' in document.createElement('div') && msie != 9;\n\n  chain.enter = function(value, event) {\n    return this.addFutureAction(\"input '\" + this.name + \"' enter '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      input.val(value);\n      input.trigger(event || (supportInputEvent ? 'input' : 'change'));\n      done();\n    });\n  };\n\n  chain.check = function() {\n    return this.addFutureAction(\"checkbox '\" + this.name + \"' toggle\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':checkbox');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.select = function(value) {\n    return this.addFutureAction(\"radio button '\" + this.name + \"' toggle '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.\n        elements('[ng\\\\:model=\"$1\"][value=\"$2\"]', this.name, value).filter(':radio');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.val = function() {\n    return this.addFutureAction(\"return input val\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      done(null,input.val());\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n\n/**\n * Usage:\n *    repeater('#products table', 'Product List').count() number of rows\n *    repeater('#products table', 'Product List').row(1) all bindings in row as an array\n *    repeater('#products table', 'Product List').column('product.name') all values across all rows in an array\n */\nangular.scenario.dsl('repeater', function() {\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.column = function(binding) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' column '\" + binding + \"'\", function($window, $document, done) {\n      done(null, $document.elements().bindings($window.angular.element, binding));\n    });\n  };\n\n  chain.row = function(index) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' row '\" + index + \"'\", function($window, $document, done) {\n      var matches = $document.elements().slice(index, index + 1);\n      if (!matches.length)\n        return done('row ' + index + ' out of bounds');\n      done(null, matches.bindings($window.angular.element));\n    });\n  };\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    select(name).option('value') select one option\n *    select(name).options('value1', 'value2', ...) select options from a multi select\n */\nangular.scenario.dsl('select', function() {\n  var chain = {};\n\n  chain.option = function(value) {\n    return this.addFutureAction(\"select '\" + this.name + \"' option '\" + value + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[ng\\\\:model=\"$1\"]', this.name);\n      var option = select.find('option[value=\"' + value + '\"]');\n      if (option.length) {\n        select.val(value);\n      } else {\n        option = select.find('option:contains(\"' + value + '\")');\n        if (option.length) {\n          select.val(option.val());\n        }\n      }\n      select.trigger('change');\n      done();\n    });\n  };\n\n  chain.options = function() {\n    var values = arguments;\n    return this.addFutureAction(\"select '\" + this.name + \"' options '\" + values + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[multiple][ng\\\\:model=\"$1\"]', this.name);\n      select.val(values);\n      select.trigger('change');\n      done();\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    element(selector, label).count() get the number of elements that match selector\n *    element(selector, label).click() clicks an element\n *    element(selector, label).query(fn) executes fn(selectedElements, done)\n *    element(selector, label).{method}() gets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(value) sets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(key) gets the value (as defined by jQuery, ex. attr)\n *    element(selector, label).{method}(key, value) sets the value (as defined by jQuery, ex. attr)\n */\nangular.scenario.dsl('element', function() {\n  var KEY_VALUE_METHODS = ['attr', 'css', 'prop'];\n  var VALUE_METHODS = [\n    'val', 'text', 'html', 'height', 'innerHeight', 'outerHeight', 'width',\n    'innerWidth', 'outerWidth', 'position', 'scrollLeft', 'scrollTop', 'offset'\n  ];\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.click = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' click\", function($window, $document, done) {\n      var elements = $document.elements();\n      var href = elements.attr('href');\n      var eventProcessDefault = elements.trigger('click')[0];\n\n      if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {\n        this.application.navigateTo(href, function() {\n          done();\n        }, done);\n      } else {\n        done();\n      }\n    });\n  };\n\n  chain.query = function(fn) {\n    return this.addFutureAction('element ' + this.label + ' custom query', function($window, $document, done) {\n      fn.call(this, $document.elements(), done);\n    });\n  };\n\n  angular.forEach(KEY_VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(name, value) {\n      var args = arguments,\n          futureName = (args.length == 1)\n              ? \"element '\" + this.label + \"' get \" + methodName + \" '\" + name + \"'\"\n              : \"element '\" + this.label + \"' set \" + methodName + \" '\" + name + \"' to \" + \"'\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  angular.forEach(VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(value) {\n      var args = arguments,\n          futureName = (args.length == 0)\n              ? \"element '\" + this.label + \"' \" + methodName\n              : futureName = \"element '\" + this.label + \"' set \" + methodName + \" to '\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Matchers for implementing specs. Follows the Jasmine spec conventions.\n */\n\nangular.scenario.matcher('toEqual', function(expected) {\n  return angular.equals(this.actual, expected);\n});\n\nangular.scenario.matcher('toBe', function(expected) {\n  return this.actual === expected;\n});\n\nangular.scenario.matcher('toBeDefined', function() {\n  return angular.isDefined(this.actual);\n});\n\nangular.scenario.matcher('toBeTruthy', function() {\n  return this.actual;\n});\n\nangular.scenario.matcher('toBeFalsy', function() {\n  return !this.actual;\n});\n\nangular.scenario.matcher('toMatch', function(expected) {\n  return new RegExp(expected).test(this.actual);\n});\n\nangular.scenario.matcher('toBeNull', function() {\n  return this.actual === null;\n});\n\nangular.scenario.matcher('toContain', function(expected) {\n  return includes(this.actual, expected);\n});\n\nangular.scenario.matcher('toBeLessThan', function(expected) {\n  return this.actual < expected;\n});\n\nangular.scenario.matcher('toBeGreaterThan', function(expected) {\n  return this.actual > expected;\n});\n\n/**\n * User Interface for the Scenario Runner.\n *\n * TODO(esprehn): This should be refactored now that ObjectModel exists\n *  to use angular bindings for the UI.\n */\nangular.scenario.output('html', function(context, runner, model) {\n  var specUiMap = {},\n      lastStepUiMap = {};\n\n  context.append(\n    '<div id=\"header\">' +\n    '  <h1><span class=\"angular\">AngularJS</span>: Scenario Test Runner</h1>' +\n    '  <ul id=\"status-legend\" class=\"status-display\">' +\n    '    <li class=\"status-error\">0 Errors</li>' +\n    '    <li class=\"status-failure\">0 Failures</li>' +\n    '    <li class=\"status-success\">0 Passed</li>' +\n    '  </ul>' +\n    '</div>' +\n    '<div id=\"specs\">' +\n    '  <div class=\"test-children\"></div>' +\n    '</div>'\n  );\n\n  runner.on('InteractivePause', function(spec) {\n    var ui = lastStepUiMap[spec.id];\n    ui.find('.test-title').\n      html('paused... <a href=\"javascript:resume()\">resume</a> when ready.');\n  });\n\n  runner.on('SpecBegin', function(spec) {\n    var ui = findContext(spec);\n    ui.find('> .tests').append(\n      '<li class=\"status-pending test-it\"></li>'\n    );\n    ui = ui.find('> .tests li:last');\n    ui.append(\n      '<div class=\"test-info\">' +\n      '  <p class=\"test-title\">' +\n      '    <span class=\"timer-result\"></span>' +\n      '    <span class=\"test-name\"></span>' +\n      '  </p>' +\n      '</div>' +\n      '<div class=\"scrollpane\">' +\n      '  <ol class=\"test-actions\"></ol>' +\n      '</div>'\n    );\n    ui.find('> .test-info .test-name').text(spec.name);\n    ui.find('> .test-info').click(function() {\n      var scrollpane = ui.find('> .scrollpane');\n      var actions = scrollpane.find('> .test-actions');\n      var name = context.find('> .test-info .test-name');\n      if (actions.find(':visible').length) {\n        actions.hide();\n        name.removeClass('open').addClass('closed');\n      } else {\n        actions.show();\n        scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n        name.removeClass('closed').addClass('open');\n      }\n    });\n\n    specUiMap[spec.id] = ui;\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var ui = specUiMap[spec.id];\n    ui.append('<pre></pre>');\n    ui.find('> pre').text(formatException(error));\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    ui.removeClass('status-pending');\n    ui.addClass('status-' + spec.status);\n    ui.find(\"> .test-info .timer-result\").text(spec.duration + \"ms\");\n    if (spec.status === 'success') {\n      ui.find('> .test-info .test-name').addClass('closed');\n      ui.find('> .scrollpane .test-actions').hide();\n    }\n    updateTotals(spec.status);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    ui.find('> .scrollpane .test-actions').append('<li class=\"status-pending\"></li>');\n    var stepUi = lastStepUiMap[spec.id] = ui.find('> .scrollpane .test-actions li:last');\n    stepUi.append(\n      '<div class=\"timer-result\"></div>' +\n      '<div class=\"test-title\"></div>'\n    );\n    stepUi.find('> .test-title').text(step.name);\n    var scrollpane = stepUi.parents('.scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepEnd', function(spec, step) {\n    var stepUi = lastStepUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    stepUi.find('.timer-result').text(step.duration + 'ms');\n    stepUi.removeClass('status-pending');\n    stepUi.addClass('status-' + step.status);\n    var scrollpane = specUiMap[spec.id].find('> .scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  /**\n   * Finds the context of a spec block defined by the passed definition.\n   *\n   * @param {Object} The definition created by the Describe object.\n   */\n  function findContext(spec) {\n    var currentContext = context.find('#specs');\n    angular.forEach(model.getDefinitionPath(spec), function(defn) {\n      var id = 'describe-' + defn.id;\n      if (!context.find('#' + id).length) {\n        currentContext.find('> .test-children').append(\n          '<div class=\"test-describe\" id=\"' + id + '\">' +\n          '  <h2></h2>' +\n          '  <div class=\"test-children\"></div>' +\n          '  <ul class=\"tests\"></ul>' +\n          '</div>'\n        );\n        context.find('#' + id).find('> h2').text('describe: ' + defn.name);\n      }\n      currentContext = context.find('#' + id);\n    });\n    return context.find('#describe-' + spec.definition.id);\n  }\n\n  /**\n   * Updates the test counter for the status.\n   *\n   * @param {string} the status.\n   */\n  function updateTotals(status) {\n    var legend = context.find('#status-legend .status-' + status);\n    var parts = legend.text().split(' ');\n    var value = (parts[0] * 1) + 1;\n    legend.text(value + ' ' + parts[1]);\n  }\n\n  /**\n   * Add an error to a step.\n   *\n   * @param {Object} The JQuery wrapped context\n   * @param {function()} fn() that should return the file/line number of the error\n   * @param {Object} the error.\n   */\n  function addError(context, line, error) {\n    context.find('.test-title').append('<pre></pre>');\n    var message = _jQuery.trim(line() + '\\n\\n' + formatException(error));\n    context.find('.test-title pre:last').text(message);\n  }\n});\n\n/**\n * Generates JSON output into a context.\n */\nangular.scenario.output('json', function(context, runner, model) {\n  model.on('RunnerEnd', function() {\n    context.text(angular.toJson(model.value));\n  });\n});\n\n/**\n * Generates XML output into a context.\n */\nangular.scenario.output('xml', function(context, runner, model) {\n  var $ = function(args) {return new context.init(args);};\n  model.on('RunnerEnd', function() {\n    var scenario = $('<scenario></scenario>');\n    context.append(scenario);\n    serializeXml(scenario, model.value);\n  });\n\n  /**\n   * Convert the tree into XML.\n   *\n   * @param {Object} context jQuery context to add the XML to.\n   * @param {Object} tree node to serialize\n   */\n  function serializeXml(context, tree) {\n     angular.forEach(tree.children, function(child) {\n       var describeContext = $('<describe></describe>');\n       describeContext.attr('id', child.id);\n       describeContext.attr('name', child.name);\n       context.append(describeContext);\n       serializeXml(describeContext, child);\n     });\n     var its = $('<its></its>');\n     context.append(its);\n     angular.forEach(tree.specs, function(spec) {\n       var it = $('<it></it>');\n       it.attr('id', spec.id);\n       it.attr('name', spec.name);\n       it.attr('duration', spec.duration);\n       it.attr('status', spec.status);\n       its.append(it);\n       angular.forEach(spec.steps, function(step) {\n         var stepContext = $('<step></step>');\n         stepContext.attr('name', step.name);\n         stepContext.attr('duration', step.duration);\n         stepContext.attr('status', step.status);\n         it.append(stepContext);\n         if (step.error) {\n           var error = $('<error></error>');\n           stepContext.append(error);\n           error.text(formatException(stepContext.error));\n         }\n       });\n     });\n   }\n});\n\n/**\n * Creates a global value $result with the result of the runner.\n */\nangular.scenario.output('object', function(context, runner, model) {\n  runner.$window.$result = model.value;\n});\nbindJQuery();\npublishExternalAPI(angular);\n\nvar $runner = new angular.scenario.Runner(window),\n    scripts = document.getElementsByTagName('script'),\n    script = scripts[scripts.length - 1],\n    config = {};\n\nangular.forEach(script.attributes, function(attr) {\n  var match = attr.name.match(/ng[:\\-](.*)/);\n  if (match) {\n    config[match[1]] = attr.value || true;\n  }\n});\n\nif (config.autotest) {\n  JQLite(document).ready(function() {\n    angular.scenario.setUpAndRun(config);\n  });\n}\n})(window, document);\n\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n\\n[ng\\\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\\n.ng-cloak, .x-ng-cloak {\\n  display: none;\\n}\\n\\nng\\\\:form {\\n  display: block;\\n}\\n</style>');\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n/* CSS Document */\\n\\n/** Structure */\\nbody {\\n  font-family: Arial, sans-serif;\\n  margin: 0;\\n  font-size: 14px;\\n}\\n\\n#system-error {\\n  font-size: 1.5em;\\n  text-align: center;\\n}\\n\\n#json, #xml {\\n  display: none;\\n}\\n\\n#header {\\n  position: fixed;\\n  width: 100%;\\n}\\n\\n#specs {\\n  padding-top: 50px;\\n}\\n\\n#header .angular {\\n  font-family: Courier New, monospace;\\n  font-weight: bold;\\n}\\n\\n#header h1 {\\n  font-weight: normal;\\n  float: left;\\n  font-size: 30px;\\n  line-height: 30px;\\n  margin: 0;\\n  padding: 10px 10px;\\n  height: 30px;\\n}\\n\\n#application h2,\\n#specs h2 {\\n  margin: 0;\\n  padding: 0.5em;\\n  font-size: 1.1em;\\n}\\n\\n#status-legend {\\n  margin-top: 10px;\\n  margin-right: 10px;\\n}\\n\\n#header,\\n#application,\\n.test-info,\\n.test-actions li {\\n  overflow: hidden;\\n}\\n\\n#application {\\n  margin: 10px;\\n}\\n\\n#application iframe {\\n  width: 100%;\\n  height: 758px;\\n}\\n\\n#application .popout {\\n  float: right;\\n}\\n\\n#application iframe {\\n  border: none;\\n}\\n\\n.tests li,\\n.test-actions li,\\n.test-it li,\\n.test-it ol,\\n.status-display {\\n  list-style-type: none;\\n}\\n\\n.tests,\\n.test-it ol,\\n.status-display {\\n  margin: 0;\\n  padding: 0;\\n}\\n\\n.test-info {\\n  margin-left: 1em;\\n  margin-top: 0.5em;\\n  border-radius: 8px 0 0 8px;\\n  -webkit-border-radius: 8px 0 0 8px;\\n  -moz-border-radius: 8px 0 0 8px;\\n  cursor: pointer;\\n}\\n\\n.test-info:hover .test-name {\\n  text-decoration: underline;\\n}\\n\\n.test-info .closed:before {\\n  content: \\'\\\\25b8\\\\00A0\\';\\n}\\n\\n.test-info .open:before {\\n  content: \\'\\\\25be\\\\00A0\\';\\n  font-weight: bold;\\n}\\n\\n.test-it ol {\\n  margin-left: 2.5em;\\n}\\n\\n.status-display,\\n.status-display li {\\n  float: right;\\n}\\n\\n.status-display li {\\n  padding: 5px 10px;\\n}\\n\\n.timer-result,\\n.test-title {\\n  display: inline-block;\\n  margin: 0;\\n  padding: 4px;\\n}\\n\\n.test-actions .test-title,\\n.test-actions .test-result {\\n  display: table-cell;\\n  padding-left: 0.5em;\\n  padding-right: 0.5em;\\n}\\n\\n.test-actions {\\n  display: table;\\n}\\n\\n.test-actions li {\\n  display: table-row;\\n}\\n\\n.timer-result {\\n  width: 4em;\\n  padding: 0 10px;\\n  text-align: right;\\n  font-family: monospace;\\n}\\n\\n.test-it pre,\\n.test-actions pre {\\n  clear: left;\\n  color: black;\\n  margin-left: 6em;\\n}\\n\\n.test-describe {\\n  padding-bottom: 0.5em;\\n}\\n\\n.test-describe .test-describe {\\n  margin: 5px 5px 10px 2em;\\n}\\n\\n.test-actions .status-pending .test-title:before {\\n  content: \\'\\\\00bb\\\\00A0\\';\\n}\\n\\n.scrollpane {\\n   max-height: 20em;\\n   overflow: auto;\\n}\\n\\n/** Colors */\\n\\n#header {\\n  background-color: #F2C200;\\n}\\n\\n#specs h2 {\\n  border-top: 2px solid #BABAD1;\\n}\\n\\n#specs h2,\\n#application h2 {\\n  background-color: #efefef;\\n}\\n\\n#application {\\n  border: 1px solid #BABAD1;\\n}\\n\\n.test-describe .test-describe {\\n  border-left: 1px solid #BABAD1;\\n  border-right: 1px solid #BABAD1;\\n  border-bottom: 1px solid #BABAD1;\\n}\\n\\n.status-display {\\n  border: 1px solid #777;\\n}\\n\\n.status-display .status-pending,\\n.status-pending .test-info {\\n  background-color: #F9EEBC;\\n}\\n\\n.status-display .status-success,\\n.status-success .test-info {\\n  background-color: #B1D7A1;\\n}\\n\\n.status-display .status-failure,\\n.status-failure .test-info {\\n  background-color: #FF8286;\\n}\\n\\n.status-display .status-error,\\n.status-error .test-info {\\n  background-color: black;\\n  color: white;\\n}\\n\\n.test-actions .status-success .test-title {\\n  color: #30B30A;\\n}\\n\\n.test-actions .status-failure .test-title {\\n  color: #DF0000;\\n}\\n\\n.test-actions .status-error .test-title {\\n  color: black;\\n}\\n\\n.test-actions .timer-result {\\n  color: #888;\\n}\\n</style>');"
  },
  {
    "path": "chapter6/recipe3/test/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter6/recipe4/README.md",
    "content": "# angular-seed — the seed for AngularJS apps\n\nThis project is an application skeleton for a typical [AngularJS](http://angularjs.org/) web app.\nYou can use it to quickly bootstrap your angular webapp projects and dev environment for these\nprojects.\n\nThe seed contains AngularJS libraries, test libraries and a bunch of scripts all preconfigured for\ninstant web development gratification. Just clone the repo (or download the zip/tarball), start up\nour (or yours) webserver and you are ready to develop and test your application.\n\nThe seed app doesn't do much, just shows how to wire two controllers and views together. You can\ncheck it out by opening app/index.html in your browser (might not work file `file://` scheme in\ncertain browsers, see note below).\n\n_Note: While angular is client-side-only technology and it's possible to create angular webapps that\ndon't require a backend server at all, we recommend hosting the project files using a local\nwebserver during development to avoid issues with security restrictions (sandbox) in browsers. The\nsandbox implementation varies between browsers, but quite often prevents things like cookies, xhr,\netc to function properly when an html page is opened via `file://` scheme instead of `http://`._\n\n\n## How to use angular-seed\n\nClone the angular-seed repository and start hacking...\n\n\n### Running the app during development\n\nYou can pick one of these options:\n\n* serve this repository with your webserver\n* install node.js and run `scripts/web-server.js`\n\nThen navigate your browser to `http://localhost:<port>/app/index.html` to see the app running in\nyour browser.\n\n\n### Running the app in production\n\nThis really depends on how complex is your app and the overall infrastructure of your system, but\nthe general rule is that all you need in production are all the files under the `app/` directory.\nEverything else should be omitted.\n\nAngular apps are really just a bunch of static html, css and js files that just need to be hosted\nsomewhere, where they can be accessed by browsers.\n\nIf your Angular app is talking to the backend server via xhr or other means, you need to figure\nout what is the best way to host the static files to comply with the same origin policy if\napplicable. Usually this is done by hosting the files by the backend server or through\nreverse-proxying the backend server(s) and a webserver(s).\n\n\n### Running unit tests\n\nWe recommend using [jasmine](http://pivotal.github.com/jasmine/) and\n[Testacular](http://vojtajina.github.com/testacular/) for your unit tests/specs, but you are free\nto use whatever works for you.\n\nRequires [node.js](http://nodejs.org/), Testacular (`sudo npm install -g testacular`) and a local\nor remote browser.\n\n* start `scripts/test.sh` (on windows: `scripts\\test.bat`)\n  * a browser will start and connect to the Testacular server (Chrome is default browser, others can be captured by loading the same url as the one in Chrome or by changing the `config/testacular.conf.js` file)\n* to run or re-run tests just change any of your source or test javascript files\n\n\n### End to end testing\n\nAngular ships with a baked-in end-to-end test runner that understands angular, your app and allows\nyou to write your tests with jasmine-like BDD syntax.\n\nRequires a webserver, node.js + `./scripts/web-server.js` or your backend server that hosts the angular static files.\n\nCheck out the\n[end-to-end runner's documentation](http://docs.angularjs.org/guide/dev_guide.e2e-testing) for more\ninfo.\n\n* create your end-to-end tests in `test/e2e/scenarios.js`\n* serve your project directory with your http/backend server or node.js + `scripts/web-server.js`\n* to run do one of:\n  * open `http://localhost:port/test/e2e/runner.html` in your browser\n  * run the tests from console with [Testacular](vojtajina.github.com/testacular) via\n    `scripts/e2e-test.sh` or `script/e2e-test.bat`\n\n\n### Receiving updates from upstream\n\nWhen we upgrade angular-seed's repo with newer angular or testing library code, you can just\nfetch the changes and merge them into your project with git.\n\n\n## Directory Layout\n\n    app/                --> all of the files to be used in production\n      css/              --> css files\n        app.css         --> default stylesheet\n      img/              --> image files\n      index.html        --> app layout file (the main html template file of the app)\n      index-async.html  --> just like index.html, but loads js files asynchronously\n      js/               --> javascript files\n        app.js          --> application\n        controllers.js  --> application controllers\n        directives.js   --> application directives\n        filters.js      --> custom angular filters\n        services.js     --> custom angular services\n      lib/              --> angular and 3rd party javascript libraries\n        angular/\n          angular.js        --> the latest angular js\n          angular.min.js    --> the latest minified angular js\n          angular-*.js      --> angular add-on modules\n          version.txt       --> version number\n      partials/             --> angular view partials (partial html templates)\n        partial1.html\n        partial2.html\n\n    config/testacular.conf.js        --> config file for running unit tests with Testacular\n    config/testacular-e2e.conf.js    --> config file for running e2e tests with Testacular\n\n    scripts/            --> handy shell/js/ruby scripts\n      e2e-test.sh       --> runs end-to-end tests with Testacular (*nix)\n      e2e-test.bat      --> runs end-to-end tests with Testacular (windows)\n      test.bat          --> autotests unit tests with Testacular (windows)\n      test.sh           --> autotests unit tests with Testacular (*nix)\n      web-server.js     --> simple development webserver based on node.js\n\n    test/               --> test source files and libraries\n      e2e/              -->\n        runner.html     --> end-to-end test runner (open in your browser to run)\n        scenarios.js    --> end-to-end specs\n      lib/\n        angular/                --> angular testing libraries\n          angular-mocks.js      --> mocks that replace certain angular services in tests\n          angular-scenario.js   --> angular's scenario (end-to-end) test runner library\n          version.txt           --> version file\n      unit/                     --> unit level specs/tests\n        controllersSpec.js      --> specs for controllers\n        directivessSpec.js      --> specs for directives\n        filtersSpec.js          --> specs for filters\n        servicesSpec.js         --> specs for services\n\n## Contact\n\nFor more information on AngularJS please check out http://angularjs.org/\n"
  },
  {
    "path": "chapter6/recipe4/app/css/.gitignore",
    "content": ""
  },
  {
    "path": "chapter6/recipe4/app/css/app.css",
    "content": "/* app css stylesheet */\n\n.menu {\n  list-style: none;\n  border-bottom: 0.1em solid black;\n  margin-bottom: 2em;\n  padding: 0 0 0.5em;\n}\n\n.menu:before {\n  content: \"[\";\n}\n\n.menu:after {\n  content: \"]\";\n}\n\n.menu > li {\n  display: inline;\n}\n\n.menu > li.active {\n  background-color: yellow;\n}\n\n.menu > li:before {\n  content: \"|\";\n  padding-right: 0.3em;\n}\n\n.menu > li:nth-child(1):before {\n  content: \"\";\n  padding: 0;\n}\n\n"
  },
  {
    "path": "chapter6/recipe4/app/img/.gitignore",
    "content": ""
  },
  {
    "path": "chapter6/recipe4/app/index.html",
    "content": "<!doctype html>\n<html lang=\"en\" ng-app=\"MyApp\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>My AngularJS App</title>\n  <link rel=\"stylesheet\" href=\"css/app.css\"/>\n</head>\n<body ng-controller=\"MainCtrl\">\n  <ul class=\"menu\">\n    <li ng-class=\"menuClass('persons')\"><a href=\"#!persons\">Home</a></li>\n    <li ng-class=\"menuClass('help')\"><a href=\"#!help\">Help</a></li>\n    <li ng-class=\"menuClass('login')\"><a href=\"#!login\">Login</a></li>\n  </ul>\n  <h1>Routing Example</h1>\n  <ng-view></ng-view>\n  <script src=\"lib/angular/angular.js\"></script>\n  <script src=\"js/app.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "chapter6/recipe4/app/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []).\n  config(function($routeProvider, $locationProvider) {\n    $locationProvider.hashPrefix('!');\n    $routeProvider.\n      when(\"/persons\", { templateUrl: \"partials/index.html\" }).\n      when(\"/persons/:id\", { templateUrl: \"partials/show.html\", controller: \"ShowCtrl\" }).\n      when(\"/login\", { templateUrl: \"partials/login.html\", controller: \"LoginCtrl\" }).\n      when(\"/help\", { templateUrl: \"partials/help.html\" }).\n      otherwise( { redirectTo: \"/persons\" });\n  }).\n  run(function($rootScope, $location) {\n\n    $rootScope.$on( \"$routeChangeStart\", function(event, next, current) {\n      if ($rootScope.loggedInUser == null) {\n        // no logged user, redirect to /login\n        if ( next.templateUrl === \"partials/login.html\") {\n        } else {\n          $location.path(\"/login\");\n        }\n      }\n    });\n  });\n\napp.factory(\"Person\", function() {\n\n  var persons = [\n    { name: \"Peter\", age: 25, id: 1 },\n    { name: \"Stefan\", age: 35, id: 2 },\n    { name: \"Agnes\", age: 22, id: 3 }\n  ];\n\n  return {\n    all: function() {\n      return persons;\n    },\n    get: function(id) {\n      var result = null;\n      angular.forEach(persons, function(p) {\n        if (p.id == id) result = p;\n      });\n      return result;\n    }\n  };\n});\n\napp.controller(\"IndexCtrl\", function($scope, Person) {\n  $scope.persons = Person.all();\n});\n\napp.controller(\"ShowCtrl\", function($scope, $routeParams, Person) {\n  $scope.person = Person.get($routeParams.id);\n});\n\napp.controller(\"MainCtrl\", function($scope, $location) {\n  $scope.menuClass = function(page) {\n    var current = $location.path().substring(1);\n    return page === current ? \"active\" : \"\";\n  };\n});\n\napp.controller(\"LoginCtrl\", function($scope, $location, $rootScope) {\n  $scope.login = function() {\n    $rootScope.loggedInUser = $scope.username;\n    $location.path(\"/persons\");\n  };\n});"
  },
  {
    "path": "chapter6/recipe4/app/lib/angular/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngCookies\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookies\n   * @requires $browser\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from\n   * this object, new cookies are created/deleted at the end of current $eval.\n   *\n   * @example\n   */\n   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for(name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            if (angular.isDefined(lastCookies[name])) {\n              cookies[name] = lastCookies[name];\n            } else {\n              delete cookies[name];\n            }\n          } else if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated){\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc object\n   * @name ngCookies.$cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   * @example\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#get\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          return angular.fromJson($cookies[key]);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#put\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name ngCookies.$cookieStore#remove\n         * @methodOf ngCookies.$cookieStore\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter6/recipe4/app/lib/angular/angular-loader.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n\n(\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n'use strict';\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n)(window);\n\n/**\n * Closure compiler type information\n *\n * @typedef { {\n *   requires: !Array.<string>,\n *   invokeQueue: !Array.<Array.<*>>,\n *\n *   service: function(string, Function):angular.Module,\n *   factory: function(string, Function):angular.Module,\n *   value: function(string, *):angular.Module,\n *\n *   filter: function(string, Function):angular.Module,\n *\n *   init: function(Function):angular.Module\n * } }\n */\nangular.Module;\n\n"
  },
  {
    "path": "chapter6/recipe4/app/lib/angular/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g. \n *   `http://example.com:8080/api`), you'll need to escape the colon character before the port\n *   number, like this: `$resource('http://example.com\\\\:8080/api')`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` – {string} – The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` – {object=} – Optional set of pre-bound parameters for this action.\n *   - isArray – {boolean=} – If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n     * encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace((pctEncodeSpaces ? null : /%20/g), '+');\n    }\n\n    function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        action.method = angular.uppercase(action.method);\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter6/recipe4/app/lib/angular/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             '<p style=\"color:blue\">an html\\n' +\n             '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n             'snippet</p>';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n          Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n           <table>\n             <tr>\n               <td>Filter</td>\n               <td>Source</td>\n               <td>Rendered</td>\n             </tr>\n             <tr id=\"html-filter\">\n               <td>html filter</td>\n               <td>\n                 <pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre>\n               </td>\n               <td>\n                 <div ng-bind-html=\"snippet\"></div>\n               </td>\n             </tr>\n             <tr id=\"escaped-html\">\n               <td>no filter</td>\n               <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind=\"snippet\"></div></td>\n             </tr>\n             <tr id=\"html-unsafe-filter\">\n               <td>unsafe html filter</td>\n               <td><pre>&lt;div ng-bind-html-unsafe=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n               <td><div ng-bind-html-unsafe=\"snippet\"></div></td>\n             </tr>\n           </table>\n         </div>\n     </doc:source>\n     <doc:scenario>\n       it('should sanitize the html snippet ', function() {\n         expect(using('#html-filter').element('div').html()).\n           toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n       });\n\n       it('should escape snippet without any filter', function() {\n         expect(using('#escaped-html').element('div').html()).\n           toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n                \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n                \"snippet&lt;/p&gt;\");\n       });\n\n       it('should inline raw snippet if filtered as unsafe', function() {\n         expect(using('#html-unsafe-filter').element(\"div\").html()).\n           toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n                \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n                \"snippet</p>\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new <b>text</b>');\n         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');\n         expect(using('#escaped-html').element('div').html()).toBe(\"new &lt;b&gt;text&lt;/b&gt;\");\n         expect(using('#html-unsafe-filter').binding(\"snippet\")).toBe('new <b>text</b>');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar $sanitize = function(html) {\n  var buf = [];\n    htmlParser(html, htmlSanitizeWriter(buf));\n    return buf.join('');\n};\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP = /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  URI_REGEXP = /^((ftp|https?):\\/\\/|mailto:|#)/,\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g; // Match everything outside of normal chars and \" (quote character)\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,aside,\" +\n        \"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,\" +\n        \"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,bdi,bdo,\" +\n        \"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,\" +\n        \"span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        index = html.indexOf(\"-->\");\n\n        if ( index >= 0 ) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'), function(all, text){\n        text = text.\n          replace(COMMENT_REGEXP, \"$1\").\n          replace(CDATA_REGEXP, \"$1\");\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n\n        return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw \"Parse Error: \" + html;\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {\n      var value = doubleQuotedValue\n        || singleQoutedValue\n        || unqoutedValue\n        || '';\n\n      attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nvar hiddenPre=document.createElement(\"pre\");\nfunction decodeEntities(value) {\n  hiddenPre.innerHTML=value.replace(/</g,\"&lt;\");\n  return hiddenPre.innerText || hiddenPre.textContent || '';\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] == true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] == true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).value('$sanitize', $sanitize);\n\n/**\n * @ngdoc directive\n * @name ngSanitize.directive:ngBindHtml\n *\n * @description\n * Creates a binding that will sanitize the result of evaluating the `expression` with the\n * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n */\nangular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);\n    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {\n      value = $sanitize(value);\n      element.html(value || '');\n    });\n  };\n}]);\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n *   plain email address links.\n *\n * @param {string} text Input text.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should linkify the snippet with urls', function() {\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('Pretty text with some links:&#10;' +\n                '<a href=\"http://angularjs.org/\">http://angularjs.org/</a>,&#10;' +\n                '<a href=\"mailto:us@somewhere.org\">us@somewhere.org</a>,&#10;' +\n                '<a href=\"mailto:another@somewhere.org\">another@somewhere.org</a>,&#10;' +\n                'and one more: <a href=\"ftp://127.0.0.1/\">ftp://127.0.0.1/</a>.');\n       });\n\n       it ('should not linkify snippet without the linky filter', function() {\n         expect(using('#escaped-html').binding('snippet')).\n           toBe(\"Pretty text with some links:\\n\" +\n                \"http://angularjs.org/,\\n\" +\n                \"mailto:us@somewhere.org,\\n\" +\n                \"another@somewhere.org,\\n\" +\n                \"and one more: ftp://127.0.0.1/.\");\n       });\n\n       it('should update', function() {\n         input('snippet').enter('new http://link.');\n         expect(using('#linky-filter').binding('snippet | linky')).\n           toBe('new <a href=\"http://link\">http://link</a>.');\n         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', function() {\n  var LINKY_URL_REGEXP = /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s\\.\\;\\,\\(\\)\\{\\}\\<\\>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    // TODO(vojta): use $sanitize instead\n    var writer = htmlSanitizeWriter(html);\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      writer.chars(raw.substr(0, i));\n      writer.start('a', {href:url});\n      writer.chars(match[0].replace(MAILTO_REGEXP, ''));\n      writer.end('a');\n      raw = raw.substring(i + match[0].length);\n    }\n    writer.chars(raw);\n    return html.join('');\n  };\n});\n\n})(window, window.angular);\n"
  },
  {
    "path": "chapter6/recipe4/app/lib/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter6/recipe4/app/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter6/recipe4/app/partials/.gitignore",
    "content": ""
  },
  {
    "path": "chapter6/recipe4/app/partials/help.html",
    "content": "<h3>Help Section</h3>\n\n<p>This is the help section</p>"
  },
  {
    "path": "chapter6/recipe4/app/partials/index.html",
    "content": "<h3>Person List</h3>\n<div ng-controller=\"IndexCtrl\">\n  <table>\n    <thead>\n      <tr>\n        <td>Name</td>\n        <td>Actions</td>\n      </tr>\n    </thead>\n    <tbody>\n      <tr ng-repeat=\"person in persons\">\n        <td>{{person.name}}</td>\n        <td><a href=\"#!persons/{{person.id}}\">Details</a></td>\n      </tr>\n    </tbody>\n  </table>\n</div>\n"
  },
  {
    "path": "chapter6/recipe4/app/partials/login.html",
    "content": "<h3>Login</h3>\n\n<form ng-submit=\"login()\">\n  <label>Username</label>\n  <input type=\"text\" ng-model=\"username\">\n  <button>Login</button>\n</form>"
  },
  {
    "path": "chapter6/recipe4/app/partials/show.html",
    "content": "<h3>{{person.name}} Details</h3>\n<p>Name: {{person.name}}</p>\n<p>Age: {{person.age}}</p>\n\n<a href=\"#!persons\">Go back</a>"
  },
  {
    "path": "chapter6/recipe4/config/testacular-e2e.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  ANGULAR_SCENARIO,\n  ANGULAR_SCENARIO_ADAPTER,\n  'test/e2e/**/*.js'\n];\n\nautoWatch = false;\n\nbrowsers = ['Chrome'];\n\nsingleRun = true;\n\nproxies = {\n  '/': 'http://localhost:8000/'\n};\n\njunitReporter = {\n  outputFile: 'test_out/e2e.xml',\n  suite: 'e2e'\n};\n"
  },
  {
    "path": "chapter6/recipe4/config/testacular.conf.js",
    "content": "basePath = '../';\n\nfiles = [\n  JASMINE,\n  JASMINE_ADAPTER,\n  'app/lib/angular/angular.js',\n  'app/lib/angular/angular-*.js',\n  'test/lib/angular/angular-mocks.js',\n  'app/js/**/*.js',\n  'test/unit/**/*.js'\n];\n\nautoWatch = true;\n\nbrowsers = ['Chrome'];\n\njunitReporter = {\n  outputFile: 'test_out/unit.xml',\n  suite: 'unit'\n};\n"
  },
  {
    "path": "chapter6/recipe4/logs/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "chapter6/recipe4/scripts/e2e-test.bat",
    "content": "@echo off\n\nREM Windows script for running e2e tests\nREM You have to run server and capture some browser first\nREM\nREM Requirements:\nREM - NodeJS (http://nodejs.org/)\nREM - Testacular (npm install -g testacular)\n\nset BASE_DIR=%~dp0\ntestacular start \"%BASE_DIR%\\..\\config\\testacular-e2e.conf.js\" %*\n"
  },
  {
    "path": "chapter6/recipe4/scripts/e2e-test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular-e2e.conf.js $*\n"
  },
  {
    "path": "chapter6/recipe4/scripts/test.bat",
    "content": "@echo off\r\n\r\nREM Windows script for running unit tests\r\nREM You have to run server and capture some browser first\r\nREM\r\nREM Requirements:\r\nREM - NodeJS (http://nodejs.org/)\r\nREM - Testacular (npm install -g testacular)\r\n\r\nset BASE_DIR=%~dp0\r\ntestacular start \"%BASE_DIR%\\..\\config\\testacular.conf.js\" %*\r\n"
  },
  {
    "path": "chapter6/recipe4/scripts/test.sh",
    "content": "#!/bin/bash\n\nBASE_DIR=`dirname $0`\n\necho \"\"\necho \"Starting Testacular Server (http://vojtajina.github.com/testacular)\"\necho \"-------------------------------------------------------------------\"\n\ntestacular start $BASE_DIR/../config/testacular.conf.js $*\n"
  },
  {
    "path": "chapter6/recipe4/scripts/watchr.rb",
    "content": "#!/usr/bin/env watchr\n\n# config file for watchr http://github.com/mynyml/watchr\n# install: gem install watchr\n# run: watch watchr.rb\n# note: make sure that you have jstd server running (server.sh) and a browser captured\n\nlog_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log')\n\n`cd ..`\n`touch #{log_file}`\n\nputs \"String watchr... log file: #{log_file}\"\n\nwatch( '(app/js|test/unit)' )  do\n  `echo \"\\n\\ntest run started @ \\`date\\`\" > #{log_file}`\n  `scripts/test.sh &> #{log_file}`\nend\n\n"
  },
  {
    "path": "chapter6/recipe4/scripts/web-server.js",
    "content": "#!/usr/bin/env node\n\nvar util = require('util'),\n    http = require('http'),\n    fs = require('fs'),\n    url = require('url'),\n    events = require('events');\n\nvar DEFAULT_PORT = 8000;\n\nfunction main(argv) {\n  new HttpServer({\n    'GET': createServlet(StaticServlet),\n    'HEAD': createServlet(StaticServlet)\n  }).start(Number(argv[2]) || DEFAULT_PORT);\n}\n\nfunction escapeHtml(value) {\n  return value.toString().\n    replace('<', '&lt;').\n    replace('>', '&gt;').\n    replace('\"', '&quot;');\n}\n\nfunction createServlet(Class) {\n  var servlet = new Class();\n  return servlet.handleRequest.bind(servlet);\n}\n\n/**\n * An Http server implementation that uses a map of methods to decide\n * action routing.\n *\n * @param {Object} Map of method => Handler function\n */\nfunction HttpServer(handlers) {\n  this.handlers = handlers;\n  this.server = http.createServer(this.handleRequest_.bind(this));\n}\n\nHttpServer.prototype.start = function(port) {\n  this.port = port;\n  this.server.listen(port);\n  util.puts('Http Server running at http://localhost:' + port + '/');\n};\n\nHttpServer.prototype.parseUrl_ = function(urlString) {\n  var parsed = url.parse(urlString);\n  parsed.pathname = url.resolve('/', parsed.pathname);\n  return url.parse(url.format(parsed), true);\n};\n\nHttpServer.prototype.handleRequest_ = function(req, res) {\n  var logEntry = req.method + ' ' + req.url;\n  if (req.headers['user-agent']) {\n    logEntry += ' ' + req.headers['user-agent'];\n  }\n  util.puts(logEntry);\n  req.url = this.parseUrl_(req.url);\n  var handler = this.handlers[req.method];\n  if (!handler) {\n    res.writeHead(501);\n    res.end();\n  } else {\n    handler.call(this, req, res);\n  }\n};\n\n/**\n * Handles static content.\n */\nfunction StaticServlet() {}\n\nStaticServlet.MimeMap = {\n  'txt': 'text/plain',\n  'html': 'text/html',\n  'css': 'text/css',\n  'xml': 'application/xml',\n  'json': 'application/json',\n  'js': 'application/javascript',\n  'jpg': 'image/jpeg',\n  'jpeg': 'image/jpeg',\n  'gif': 'image/gif',\n  'png': 'image/png',\n  'svg': 'image/svg+xml'\n};\n\nStaticServlet.prototype.handleRequest = function(req, res) {\n  var self = this;\n  var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){\n    return String.fromCharCode(parseInt(hex, 16));\n  });\n  var parts = path.split('/');\n  if (parts[parts.length-1].charAt(0) === '.')\n    return self.sendForbidden_(req, res, path);\n  fs.stat(path, function(err, stat) {\n    if (err)\n      return self.sendMissing_(req, res, path);\n    if (stat.isDirectory())\n      return self.sendDirectory_(req, res, path);\n    return self.sendFile_(req, res, path);\n  });\n}\n\nStaticServlet.prototype.sendError_ = function(req, res, error) {\n  res.writeHead(500, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>Internal Server Error</title>\\n');\n  res.write('<h1>Internal Server Error</h1>');\n  res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');\n  util.puts('500 Internal Server Error');\n  util.puts(util.inspect(error));\n};\n\nStaticServlet.prototype.sendMissing_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(404, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>404 Not Found</title>\\n');\n  res.write('<h1>Not Found</h1>');\n  res.write(\n    '<p>The requested URL ' +\n    escapeHtml(path) +\n    ' was not found on this server.</p>'\n  );\n  res.end();\n  util.puts('404 Not Found: ' + path);\n};\n\nStaticServlet.prototype.sendForbidden_ = function(req, res, path) {\n  path = path.substring(1);\n  res.writeHead(403, {\n      'Content-Type': 'text/html'\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>403 Forbidden</title>\\n');\n  res.write('<h1>Forbidden</h1>');\n  res.write(\n    '<p>You do not have permission to access ' +\n    escapeHtml(path) + ' on this server.</p>'\n  );\n  res.end();\n  util.puts('403 Forbidden: ' + path);\n};\n\nStaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {\n  res.writeHead(301, {\n      'Content-Type': 'text/html',\n      'Location': redirectUrl\n  });\n  res.write('<!doctype html>\\n');\n  res.write('<title>301 Moved Permanently</title>\\n');\n  res.write('<h1>Moved Permanently</h1>');\n  res.write(\n    '<p>The document has moved <a href=\"' +\n    redirectUrl +\n    '\">here</a>.</p>'\n  );\n  res.end();\n  util.puts('301 Moved Permanently: ' + redirectUrl);\n};\n\nStaticServlet.prototype.sendFile_ = function(req, res, path) {\n  var self = this;\n  var file = fs.createReadStream(path);\n  res.writeHead(200, {\n    'Content-Type': StaticServlet.\n      MimeMap[path.split('.').pop()] || 'text/plain'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n  } else {\n    file.on('data', res.write.bind(res));\n    file.on('close', function() {\n      res.end();\n    });\n    file.on('error', function(error) {\n      self.sendError_(req, res, error);\n    });\n  }\n};\n\nStaticServlet.prototype.sendDirectory_ = function(req, res, path) {\n  var self = this;\n  if (path.match(/[^\\/]$/)) {\n    req.url.pathname += '/';\n    var redirectUrl = url.format(url.parse(url.format(req.url)));\n    return self.sendRedirect_(req, res, redirectUrl);\n  }\n  fs.readdir(path, function(err, files) {\n    if (err)\n      return self.sendError_(req, res, error);\n\n    if (!files.length)\n      return self.writeDirectoryIndex_(req, res, path, []);\n\n    var remaining = files.length;\n    files.forEach(function(fileName, index) {\n      fs.stat(path + '/' + fileName, function(err, stat) {\n        if (err)\n          return self.sendError_(req, res, err);\n        if (stat.isDirectory()) {\n          files[index] = fileName + '/';\n        }\n        if (!(--remaining))\n          return self.writeDirectoryIndex_(req, res, path, files);\n      });\n    });\n  });\n};\n\nStaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {\n  path = path.substring(1);\n  res.writeHead(200, {\n    'Content-Type': 'text/html'\n  });\n  if (req.method === 'HEAD') {\n    res.end();\n    return;\n  }\n  res.write('<!doctype html>\\n');\n  res.write('<title>' + escapeHtml(path) + '</title>\\n');\n  res.write('<style>\\n');\n  res.write('  ol { list-style-type: none; font-size: 1.2em; }\\n');\n  res.write('</style>\\n');\n  res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');\n  res.write('<ol>');\n  files.forEach(function(fileName) {\n    if (fileName.charAt(0) !== '.') {\n      res.write('<li><a href=\"' +\n        escapeHtml(fileName) + '\">' +\n        escapeHtml(fileName) + '</a></li>');\n    }\n  });\n  res.write('</ol>');\n  res.end();\n};\n\n// Must be last,\nmain(process.argv);\n"
  },
  {
    "path": "chapter6/recipe4/test/e2e/runner.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <title>End2end Test Runner</title>\n    <script src=\"../lib/angular/angular-scenario.js\" ng-autotest></script>\n    <script src=\"scenarios.js\"></script>\n  </head>\n  <body>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter6/recipe4/test/e2e/scenarios.js",
    "content": "'use strict';\n\n/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */\n\ndescribe('my app', function() {\n\n  beforeEach(function() {\n    browser().navigateTo('../../app/index.html');\n  });\n\n\n  it('should automatically redirect to /view1 when location hash/fragment is empty', function() {\n    expect(browser().location().url()).toBe(\"/view1\");\n  });\n\n\n  describe('view1', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view1');\n    });\n\n\n    it('should render view1 when user navigates to /view1', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 1/);\n    });\n\n  });\n\n\n  describe('view2', function() {\n\n    beforeEach(function() {\n      browser().navigateTo('#/view2');\n    });\n\n\n    it('should render view2 when user navigates to /view2', function() {\n      expect(element('[ng-view] p:first').text()).\n        toMatch(/partial for view 2/);\n    });\n\n  });\n});\n"
  },
  {
    "path": "chapter6/recipe4/test/lib/angular/angular-mocks.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n *\n * TODO(vojta): wrap whole file into closure during build\n */\n\n/**\n * @ngdoc overview\n * @name angular.mock\n * @description\n *\n * Namespace from 'angular-mocks.js' which contains testing related code.\n */\nangular.mock = {};\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ngMock.$browser\n *\n * @description\n * This service is a mock implementation of {@link ng.$browser}. It provides fake\n * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,\n * cookies, etc...\n *\n * The api of this service is the same as that of the real {@link ng.$browser $browser}, except\n * that there are several helper methods available which can be used in tests.\n */\nangular.mock.$BrowserProvider = function() {\n  this.$get = function(){\n    return new angular.mock.$Browser();\n  };\n};\n\nangular.mock.$Browser = function() {\n  var self = this;\n\n  this.isMock = true;\n  self.$$url = \"http://server/\";\n  self.$$lastUrl = self.$$url; // used by url polling fn\n  self.pollFns = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = angular.noop;\n  self.$$incOutstandingRequestCount = angular.noop;\n\n\n  // register url polling fn\n\n  self.onUrlChange = function(listener) {\n    self.pollFns.push(\n      function() {\n        if (self.$$lastUrl != self.$$url) {\n          self.$$lastUrl = self.$$url;\n          listener(self.$$url);\n        }\n      }\n    );\n\n    return listener;\n  };\n\n  self.cookieHash = {};\n  self.lastCookieHash = {};\n  self.deferredFns = [];\n  self.deferredNextId = 0;\n\n  self.defer = function(fn, delay) {\n    delay = delay || 0;\n    self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});\n    self.deferredFns.sort(function(a,b){ return a.time - b.time;});\n    return self.deferredNextId++;\n  };\n\n\n  self.defer.now = 0;\n\n\n  self.defer.cancel = function(deferId) {\n    var fnIndex;\n\n    angular.forEach(self.deferredFns, function(fn, index) {\n      if (fn.id === deferId) fnIndex = index;\n    });\n\n    if (fnIndex !== undefined) {\n      self.deferredFns.splice(fnIndex, 1);\n      return true;\n    }\n\n    return false;\n  };\n\n\n  /**\n   * @name ngMock.$browser#defer.flush\n   * @methodOf ngMock.$browser\n   *\n   * @description\n   * Flushes all pending requests and executes the defer callbacks.\n   *\n   * @param {number=} number of milliseconds to flush. See {@link #defer.now}\n   */\n  self.defer.flush = function(delay) {\n    if (angular.isDefined(delay)) {\n      self.defer.now += delay;\n    } else {\n      if (self.deferredFns.length) {\n        self.defer.now = self.deferredFns[self.deferredFns.length-1].time;\n      } else {\n        throw Error('No deferred tasks to be flushed');\n      }\n    }\n\n    while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {\n      self.deferredFns.shift().fn();\n    }\n  };\n  /**\n   * @name ngMock.$browser#defer.now\n   * @propertyOf ngMock.$browser\n   *\n   * @description\n   * Current milliseconds mock time.\n   */\n\n  self.$$baseHref = '';\n  self.baseHref = function() {\n    return this.$$baseHref;\n  };\n};\nangular.mock.$Browser.prototype = {\n\n/**\n  * @name ngMock.$browser#poll\n  * @methodOf ngMock.$browser\n  *\n  * @description\n  * run all fns in pollFns\n  */\n  poll: function poll() {\n    angular.forEach(this.pollFns, function(pollFn){\n      pollFn();\n    });\n  },\n\n  addPollFn: function(pollFn) {\n    this.pollFns.push(pollFn);\n    return pollFn;\n  },\n\n  url: function(url, replace) {\n    if (url) {\n      this.$$url = url;\n      return this;\n    }\n\n    return this.$$url;\n  },\n\n  cookies:  function(name, value) {\n    if (name) {\n      if (value == undefined) {\n        delete this.cookieHash[name];\n      } else {\n        if (angular.isString(value) &&       //strings only\n            value.length <= 4096) {          //strict cookie storage limits\n          this.cookieHash[name] = value;\n        }\n      }\n    } else {\n      if (!angular.equals(this.cookieHash, this.lastCookieHash)) {\n        this.lastCookieHash = angular.copy(this.cookieHash);\n        this.cookieHash = angular.copy(this.cookieHash);\n      }\n      return this.cookieHash;\n    }\n  },\n\n  notifyWhenNoOutstandingRequests: function(fn) {\n    fn();\n  }\n};\n\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandlerProvider\n *\n * @description\n * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed\n * into the `$exceptionHandler`.\n */\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandler\n *\n * @description\n * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed\n * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration\n * information.\n *\n *\n * <pre>\n *   describe('$exceptionHandlerProvider', function() {\n *\n *     it('should capture log messages and exceptions', function() {\n *\n *       module(function($exceptionHandlerProvider) {\n *         $exceptionHandlerProvider.mode('log');\n *       });\n *\n *       inject(function($log, $exceptionHandler, $timeout) {\n *         $timeout(function() { $log.log(1); });\n *         $timeout(function() { $log.log(2); throw 'banana peel'; });\n *         $timeout(function() { $log.log(3); });\n *         expect($exceptionHandler.errors).toEqual([]);\n *         expect($log.assertEmpty());\n *         $timeout.flush();\n *         expect($exceptionHandler.errors).toEqual(['banana peel']);\n *         expect($log.log.logs).toEqual([[1], [2], [3]]);\n *       });\n *     });\n *   });\n * </pre>\n */\n\nangular.mock.$ExceptionHandlerProvider = function() {\n  var handler;\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$exceptionHandlerProvider#mode\n   * @methodOf ngMock.$exceptionHandlerProvider\n   *\n   * @description\n   * Sets the logging mode.\n   *\n   * @param {string} mode Mode of operation, defaults to `rethrow`.\n   *\n   *   - `rethrow`: If any errors are are passed into the handler in tests, it typically\n   *                means that there is a bug in the application or test, so this mock will\n   *                make these tests fail.\n   *   - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores an\n   *            array of errors in `$exceptionHandler.errors`, to allow later assertion of them.\n   *            See {@link ngMock.$log#assertEmpty assertEmpty()} and\n   *             {@link ngMock.$log#reset reset()}\n   */\n  this.mode = function(mode) {\n    switch(mode) {\n      case 'rethrow':\n        handler = function(e) {\n          throw e;\n        };\n        break;\n      case 'log':\n        var errors = [];\n\n        handler = function(e) {\n          if (arguments.length == 1) {\n            errors.push(e);\n          } else {\n            errors.push([].slice.call(arguments, 0));\n          }\n        };\n\n        handler.errors = errors;\n        break;\n      default:\n        throw Error(\"Unknown mode '\" + mode + \"', only 'log'/'rethrow' modes are allowed!\");\n    }\n  };\n\n  this.$get = function() {\n    return handler;\n  };\n\n  this.mode('rethrow');\n};\n\n\n/**\n * @ngdoc service\n * @name ngMock.$log\n *\n * @description\n * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays\n * (one array per logging level). These arrays are exposed as `logs` property of each of the\n * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.\n *\n */\nangular.mock.$LogProvider = function() {\n\n  function concat(array1, array2, index) {\n    return array1.concat(Array.prototype.slice.call(array2, index));\n  }\n\n\n  this.$get = function () {\n    var $log = {\n      log: function() { $log.log.logs.push(concat([], arguments, 0)); },\n      warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },\n      info: function() { $log.info.logs.push(concat([], arguments, 0)); },\n      error: function() { $log.error.logs.push(concat([], arguments, 0)); }\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#reset\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Reset all of the logging arrays to empty.\n     */\n    $log.reset = function () {\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#log.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.log.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#warn.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.warn.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#info.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.info.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#error.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of logged messages.\n       */\n      $log.error.logs = [];\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#assertEmpty\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.\n     */\n    $log.assertEmpty = function() {\n      var errors = [];\n      angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {\n        angular.forEach($log[logLevel].logs, function(log) {\n          angular.forEach(log, function (logItem) {\n            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\\n' + (logItem.stack || ''));\n          });\n        });\n      });\n      if (errors.length) {\n        errors.unshift(\"Expected $log to be empty! Either a message was logged unexpectedly, or an expected \" +\n          \"log message was not checked and removed:\");\n        errors.push('');\n        throw new Error(errors.join('\\n---------\\n'));\n      }\n    };\n\n    $log.reset();\n    return $log;\n  };\n};\n\n\n(function() {\n  var R_ISO8061_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?:\\:?(\\d\\d)(?:\\:?(\\d\\d)(?:\\.(\\d{3}))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d)))?$/;\n\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8061_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n  function int(str) {\n    return parseInt(str, 10);\n  }\n\n  function padNumber(num, digits, trim) {\n    var neg = '';\n    if (num < 0) {\n      neg =  '-';\n      num = -num;\n    }\n    num = '' + num;\n    while(num.length < digits) num = '0' + num;\n    if (trim)\n      num = num.substr(num.length - digits);\n    return neg + num;\n  }\n\n\n  /**\n   * @ngdoc object\n   * @name angular.mock.TzDate\n   * @description\n   *\n   * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.\n   *\n   * Mock of the Date type which has its timezone specified via constroctor arg.\n   *\n   * The main purpose is to create Date-like instances with timezone fixed to the specified timezone\n   * offset, so that we can test code that depends on local timezone settings without dependency on\n   * the time zone settings of the machine where the code is running.\n   *\n   * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)\n   * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*\n   *\n   * @example\n   * !!!! WARNING !!!!!\n   * This is not a complete Date object so only methods that were implemented can be called safely.\n   * To make matters worse, TzDate instances inherit stuff from Date via a prototype.\n   *\n   * We do our best to intercept calls to \"unimplemented\" methods, but since the list of methods is\n   * incomplete we might be missing some non-standard methods. This can result in errors like:\n   * \"Date.prototype.foo called on incompatible Object\".\n   *\n   * <pre>\n   * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');\n   * newYearInBratislava.getTimezoneOffset() => -60;\n   * newYearInBratislava.getFullYear() => 2010;\n   * newYearInBratislava.getMonth() => 0;\n   * newYearInBratislava.getDate() => 1;\n   * newYearInBratislava.getHours() => 0;\n   * newYearInBratislava.getMinutes() => 0;\n   * </pre>\n   *\n   */\n  angular.mock.TzDate = function (offset, timestamp) {\n    var self = new Date(0);\n    if (angular.isString(timestamp)) {\n      var tsStr = timestamp;\n\n      self.origDate = jsonStringToDate(timestamp);\n\n      timestamp = self.origDate.getTime();\n      if (isNaN(timestamp))\n        throw {\n          name: \"Illegal Argument\",\n          message: \"Arg '\" + tsStr + \"' passed into TzDate constructor is not a valid date string\"\n        };\n    } else {\n      self.origDate = new Date(timestamp);\n    }\n\n    var localOffset = new Date(timestamp).getTimezoneOffset();\n    self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;\n    self.date = new Date(timestamp + self.offsetDiff);\n\n    self.getTime = function() {\n      return self.date.getTime() - self.offsetDiff;\n    };\n\n    self.toLocaleDateString = function() {\n      return self.date.toLocaleDateString();\n    };\n\n    self.getFullYear = function() {\n      return self.date.getFullYear();\n    };\n\n    self.getMonth = function() {\n      return self.date.getMonth();\n    };\n\n    self.getDate = function() {\n      return self.date.getDate();\n    };\n\n    self.getHours = function() {\n      return self.date.getHours();\n    };\n\n    self.getMinutes = function() {\n      return self.date.getMinutes();\n    };\n\n    self.getSeconds = function() {\n      return self.date.getSeconds();\n    };\n\n    self.getTimezoneOffset = function() {\n      return offset * 60;\n    };\n\n    self.getUTCFullYear = function() {\n      return self.origDate.getUTCFullYear();\n    };\n\n    self.getUTCMonth = function() {\n      return self.origDate.getUTCMonth();\n    };\n\n    self.getUTCDate = function() {\n      return self.origDate.getUTCDate();\n    };\n\n    self.getUTCHours = function() {\n      return self.origDate.getUTCHours();\n    };\n\n    self.getUTCMinutes = function() {\n      return self.origDate.getUTCMinutes();\n    };\n\n    self.getUTCSeconds = function() {\n      return self.origDate.getUTCSeconds();\n    };\n\n    self.getUTCMilliseconds = function() {\n      return self.origDate.getUTCMilliseconds();\n    };\n\n    self.getDay = function() {\n      return self.date.getDay();\n    };\n\n    // provide this method only on browsers that already have it\n    if (self.toISOString) {\n      self.toISOString = function() {\n        return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +\n              padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +\n              padNumber(self.origDate.getUTCDate(), 2) + 'T' +\n              padNumber(self.origDate.getUTCHours(), 2) + ':' +\n              padNumber(self.origDate.getUTCMinutes(), 2) + ':' +\n              padNumber(self.origDate.getUTCSeconds(), 2) + '.' +\n              padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'\n      }\n    }\n\n    //hide all methods not implemented in this mock that the Date prototype exposes\n    var unimplementedMethods = ['getMilliseconds', 'getUTCDay',\n        'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',\n        'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',\n        'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',\n        'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',\n        'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];\n\n    angular.forEach(unimplementedMethods, function(methodName) {\n      self[methodName] = function() {\n        throw Error(\"Method '\" + methodName + \"' is not implemented in the TzDate mock\");\n      };\n    });\n\n    return self;\n  };\n\n  //make \"tzDateInstance instanceof Date\" return true\n  angular.mock.TzDate.prototype = Date.prototype;\n})();\n\n\n/**\n * @ngdoc function\n * @name angular.mock.dump\n * @description\n *\n * *NOTE*: this is not an injectable instance, just a globally available function.\n *\n * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.\n *\n * This method is also available on window, where it can be used to display objects on debug console.\n *\n * @param {*} object - any object to turn into string.\n * @return {string} a serialized string of the argument\n */\nangular.mock.dump = function(object) {\n  return serialize(object);\n\n  function serialize(object) {\n    var out;\n\n    if (angular.isElement(object)) {\n      object = angular.element(object);\n      out = angular.element('<div></div>');\n      angular.forEach(object, function(element) {\n        out.append(angular.element(element).clone());\n      });\n      out = out.html();\n    } else if (angular.isArray(object)) {\n      out = [];\n      angular.forEach(object, function(o) {\n        out.push(serialize(o));\n      });\n      out = '[ ' + out.join(', ') + ' ]';\n    } else if (angular.isObject(object)) {\n      if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {\n        out = serializeScope(object);\n      } else if (object instanceof Error) {\n        out = object.stack || ('' + object.name + ': ' + object.message);\n      } else {\n        out = angular.toJson(object, true);\n      }\n    } else {\n      out = String(object);\n    }\n\n    return out;\n  }\n\n  function serializeScope(scope, offset) {\n    offset = offset ||  '  ';\n    var log = [offset + 'Scope(' + scope.$id + '): {'];\n    for ( var key in scope ) {\n      if (scope.hasOwnProperty(key) && !key.match(/^(\\$|this)/)) {\n        log.push('  ' + key + ': ' + angular.toJson(scope[key]));\n      }\n    }\n    var child = scope.$$childHead;\n    while(child) {\n      log.push(serializeScope(child, offset + '  '));\n      child = child.$$nextSibling;\n    }\n    log.push('}');\n    return log.join('\\n' + offset);\n  }\n};\n\n/**\n * @ngdoc object\n * @name ngMock.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for unit testing application that use the\n * {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less\n * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.\n *\n * During unit testing, we want our unit tests to run quickly and have no external dependencies so\n * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or\n * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is\n * to verify whether a certain request has been sent or not, or alternatively just let the\n * application make requests, respond with pre-trained responses and assert that the end result is\n * what we expect it to be.\n *\n * This mock implementation can be used to respond with static or dynamic responses via the\n * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).\n *\n * When an Angular application needs some data from a server, it calls the $http service, which\n * sends the request to a real server using $httpBackend service. With dependency injection, it is\n * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify\n * the requests and respond with some testing data without sending a request to real server.\n *\n * There are two ways to specify what test data should be returned as http responses by the mock\n * backend when the code under test makes http requests:\n *\n * - `$httpBackend.expect` - specifies a request expectation\n * - `$httpBackend.when` - specifies a backend definition\n *\n *\n * # Request Expectations vs Backend Definitions\n *\n * Request expectations provide a way to make assertions about requests made by the application and\n * to define responses for those requests. The test will fail if the expected requests are not made\n * or they are made in the wrong order.\n *\n * Backend definitions allow you to define a fake backend for your application which doesn't assert\n * if a particular request was made or not, it just returns a trained response if a request is made.\n * The test will pass whether or not the request gets made during testing.\n *\n *\n * <table class=\"table\">\n *   <tr><th width=\"220px\"></th><th>Request expectations</th><th>Backend definitions</th></tr>\n *   <tr>\n *     <th>Syntax</th>\n *     <td>.expect(...).respond(...)</td>\n *     <td>.when(...).respond(...)</td>\n *   </tr>\n *   <tr>\n *     <th>Typical usage</th>\n *     <td>strict unit tests</td>\n *     <td>loose (black-box) unit testing</td>\n *   </tr>\n *   <tr>\n *     <th>Fulfills multiple requests</th>\n *     <td>NO</td>\n *     <td>YES</td>\n *   </tr>\n *   <tr>\n *     <th>Order of requests matters</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Request required</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Response required</th>\n *     <td>optional (see below)</td>\n *     <td>YES</td>\n *   </tr>\n * </table>\n *\n * In cases where both backend definitions and request expectations are specified during unit\n * testing, the request expectations are evaluated first.\n *\n * If a request expectation has no response specified, the algorithm will search your backend\n * definitions for an appropriate response.\n *\n * If a request didn't match any expectation or if the expectation doesn't have the response\n * defined, the backend definitions are evaluated in sequential order to see if any of them match\n * the request. The response from the first matched definition is returned.\n *\n *\n * # Flushing HTTP requests\n *\n * The $httpBackend used in production, always responds to requests with responses asynchronously.\n * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are\n * hard to write, follow and maintain. At the same time the testing mock, can't respond\n * synchronously because that would change the execution of the code under test. For this reason the\n * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending\n * requests and thus preserving the async api of the backend, while allowing the test to execute\n * synchronously.\n *\n *\n * # Unit testing with mock $httpBackend\n *\n * <pre>\n   // controller\n   function MyController($scope, $http) {\n     $http.get('/auth.py').success(function(data) {\n       $scope.user = data;\n     });\n\n     this.saveMessage = function(message) {\n       $scope.status = 'Saving...';\n       $http.post('/add-msg.py', message).success(function(response) {\n         $scope.status = '';\n       }).error(function() {\n         $scope.status = 'ERROR!';\n       });\n     };\n   }\n\n   // testing controller\n   var $httpBackend;\n\n   beforeEach(inject(function($injector) {\n     $httpBackend = $injector.get('$httpBackend');\n\n     // backend definition common for all tests\n     $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});\n   }));\n\n\n   afterEach(function() {\n     $httpBackend.verifyNoOutstandingExpectation();\n     $httpBackend.verifyNoOutstandingRequest();\n   });\n\n\n   it('should fetch authentication token', function() {\n     $httpBackend.expectGET('/auth.py');\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n   });\n\n\n   it('should send msg to server', function() {\n     // now you don’t care about the authentication, but\n     // the controller will still send the request and\n     // $httpBackend will respond without you having to\n     // specify the expectation and response for this request\n     $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');\n\n     var controller = scope.$new(MyController);\n     $httpBackend.flush();\n     controller.saveMessage('message content');\n     expect(controller.status).toBe('Saving...');\n     $httpBackend.flush();\n     expect(controller.status).toBe('');\n   });\n\n\n   it('should send auth header', function() {\n     $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {\n       // check if the header was send, if it wasn't the expectation won't\n       // match the request and the test will fail\n       return headers['Authorization'] == 'xxx';\n     }).respond(201, '');\n\n     var controller = scope.$new(MyController);\n     controller.saveMessage('whatever');\n     $httpBackend.flush();\n   });\n   </pre>\n */\nangular.mock.$HttpBackendProvider = function() {\n  this.$get = [createHttpBackendMock];\n};\n\n/**\n * General factory function for $httpBackend mock.\n * Returns instance for unit testing (when no arguments specified):\n *   - passing through is disabled\n *   - auto flushing is disabled\n *\n * Returns instance for e2e testing (when `$delegate` and `$browser` specified):\n *   - passing through (delegating request to real backend) is enabled\n *   - auto flushing is enabled\n *\n * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)\n * @param {Object=} $browser Auto-flushing enabled if specified\n * @return {Object} Instance of $httpBackend mock\n */\nfunction createHttpBackendMock($delegate, $browser) {\n  var definitions = [],\n      expectations = [],\n      responses = [],\n      responsesPush = angular.bind(responses, responses.push);\n\n  function createResponse(status, data, headers) {\n    if (angular.isFunction(status)) return status;\n\n    return function() {\n      return angular.isNumber(status)\n          ? [status, data, headers]\n          : [200, status, data];\n    };\n  }\n\n  // TODO(vojta): change params to: method, url, data, headers, callback\n  function $httpBackend(method, url, data, callback, headers) {\n    var xhr = new MockXhr(),\n        expectation = expectations[0],\n        wasExpected = false;\n\n    function prettyPrint(data) {\n      return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)\n          ? data\n          : angular.toJson(data);\n    }\n\n    if (expectation && expectation.match(method, url)) {\n      if (!expectation.matchData(data))\n        throw Error('Expected ' + expectation + ' with different data\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.data) + '\\nGOT:      ' + data);\n\n      if (!expectation.matchHeaders(headers))\n        throw Error('Expected ' + expectation + ' with different headers\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.headers) + '\\nGOT:      ' +\n            prettyPrint(headers));\n\n      expectations.shift();\n\n      if (expectation.response) {\n        responses.push(function() {\n          var response = expectation.response(method, url, data, headers);\n          xhr.$$respHeaders = response[2];\n          callback(response[0], response[1], xhr.getAllResponseHeaders());\n        });\n        return;\n      }\n      wasExpected = true;\n    }\n\n    var i = -1, definition;\n    while ((definition = definitions[++i])) {\n      if (definition.match(method, url, data, headers || {})) {\n        if (definition.response) {\n          // if $browser specified, we do auto flush all requests\n          ($browser ? $browser.defer : responsesPush)(function() {\n            var response = definition.response(method, url, data, headers);\n            xhr.$$respHeaders = response[2];\n            callback(response[0], response[1], xhr.getAllResponseHeaders());\n          });\n        } else if (definition.passThrough) {\n          $delegate(method, url, data, callback, headers);\n        } else throw Error('No response defined !');\n        return;\n      }\n    }\n    throw wasExpected ?\n        Error('No response defined !') :\n        Error('Unexpected request: ' + method + ' ' + url + '\\n' +\n              (expectation ? 'Expected ' + expectation : 'No more request expected'));\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#when\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current definition.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.when = function(method, url, data, headers) {\n    var definition = new MockHttpExpectation(method, url, data, headers),\n        chain = {\n          respond: function(status, data, headers) {\n            definition.response = createResponse(status, data, headers);\n          }\n        };\n\n    if ($browser) {\n      chain.passThrough = function() {\n        definition.passThrough = true;\n      };\n    }\n\n    definitions.push(definition);\n    return chain;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for GET requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for HEAD requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for DELETE requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for POST requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for PUT requests.  For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for JSONP requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n  createShortMethods('when');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expect\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current expectation.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *  request is handled.\n   *\n   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.expect = function(method, url, data, headers) {\n    var expectation = new MockHttpExpectation(method, url, data, headers);\n    expectations.push(expectation);\n    return {\n      respond: function(status, data, headers) {\n        expectation.response = createResponse(status, data, headers);\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for GET requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled. See #expect for more info.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for HEAD requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for DELETE requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for POST requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PUT requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPATCH\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PATCH requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp)=} data HTTP request body.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for JSONP requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n  createShortMethods('expect');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#flush\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Flushes all pending requests using the trained responses.\n   *\n   * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,\n   *   all pending requests will be flushed. If there are no pending requests when the flush method\n   *   is called an exception is thrown (as this typically a sign of programming error).\n   */\n  $httpBackend.flush = function(count) {\n    if (!responses.length) throw Error('No pending request to flush !');\n\n    if (angular.isDefined(count)) {\n      while (count--) {\n        if (!responses.length) throw Error('No more pending request to flush !');\n        responses.shift()();\n      }\n    } else {\n      while (responses.length) {\n        responses.shift()();\n      }\n    }\n    $httpBackend.verifyNoOutstandingExpectation();\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingExpectation\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that all of the requests defined via the `expect` api were made. If any of the\n   * requests were not made, verifyNoOutstandingExpectation throws an exception.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyExpectations);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingExpectation = function() {\n    if (expectations.length) {\n      throw Error('Unsatisfied requests: ' + expectations.join(', '));\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingRequest\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that there are no outstanding requests that need to be flushed.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyNoOutstandingRequest);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingRequest = function() {\n    if (responses.length) {\n      throw Error('Unflushed requests: ' + responses.length);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#resetExpectations\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Resets all request expectations, but preserves all backend definitions. Typically, you would\n   * call resetExpectations during a multiple-phase test when you want to reuse the same instance of\n   * $httpBackend mock.\n   */\n  $httpBackend.resetExpectations = function() {\n    expectations.length = 0;\n    responses.length = 0;\n  };\n\n  return $httpBackend;\n\n\n  function createShortMethods(prefix) {\n    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {\n     $httpBackend[prefix + method] = function(url, headers) {\n       return $httpBackend[prefix](method, url, undefined, headers)\n     }\n    });\n\n    angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {\n      $httpBackend[prefix + method] = function(url, data, headers) {\n        return $httpBackend[prefix](method, url, data, headers)\n      }\n    });\n  }\n}\n\nfunction MockHttpExpectation(method, url, data, headers) {\n\n  this.data = data;\n  this.headers = headers;\n\n  this.match = function(m, u, d, h) {\n    if (method != m) return false;\n    if (!this.matchUrl(u)) return false;\n    if (angular.isDefined(d) && !this.matchData(d)) return false;\n    if (angular.isDefined(h) && !this.matchHeaders(h)) return false;\n    return true;\n  };\n\n  this.matchUrl = function(u) {\n    if (!url) return true;\n    if (angular.isFunction(url.test)) return url.test(u);\n    return url == u;\n  };\n\n  this.matchHeaders = function(h) {\n    if (angular.isUndefined(headers)) return true;\n    if (angular.isFunction(headers)) return headers(h);\n    return angular.equals(headers, h);\n  };\n\n  this.matchData = function(d) {\n    if (angular.isUndefined(data)) return true;\n    if (data && angular.isFunction(data.test)) return data.test(d);\n    if (data && !angular.isString(data)) return angular.toJson(data) == d;\n    return data == d;\n  };\n\n  this.toString = function() {\n    return method + ' ' + url;\n  };\n}\n\nfunction MockXhr() {\n\n  // hack for testing $http, $httpBackend\n  MockXhr.$$lastInstance = this;\n\n  this.open = function(method, url, async) {\n    this.$$method = method;\n    this.$$url = url;\n    this.$$async = async;\n    this.$$reqHeaders = {};\n    this.$$respHeaders = {};\n  };\n\n  this.send = function(data) {\n    this.$$data = data;\n  };\n\n  this.setRequestHeader = function(key, value) {\n    this.$$reqHeaders[key] = value;\n  };\n\n  this.getResponseHeader = function(name) {\n    // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last\n    var header = this.$$respHeaders[name];\n    if (header) return header;\n\n    name = angular.lowercase(name);\n    header = this.$$respHeaders[name];\n    if (header) return header;\n\n    header = undefined;\n    angular.forEach(this.$$respHeaders, function(headerVal, headerName) {\n      if (!header && angular.lowercase(headerName) == name) header = headerVal;\n    });\n    return header;\n  };\n\n  this.getAllResponseHeaders = function() {\n    var lines = [];\n\n    angular.forEach(this.$$respHeaders, function(value, key) {\n      lines.push(key + ': ' + value);\n    });\n    return lines.join('\\n');\n  };\n\n  this.abort = angular.noop;\n}\n\n\n/**\n * @ngdoc function\n * @name ngMock.$timeout\n * @description\n *\n * This service is just a simple decorator for {@link ng.$timeout $timeout} service\n * that adds a \"flush\" method.\n */\n\n/**\n * @ngdoc method\n * @name ngMock.$timeout#flush\n * @methodOf ngMock.$timeout\n * @description\n *\n * Flushes the queue of pending tasks.\n */\n\n/**\n *\n */\nangular.mock.$RootElementProvider = function() {\n  this.$get = function() {\n    return angular.element('<div ng-app></div>');\n  }\n};\n\n/**\n * @ngdoc overview\n * @name ngMock\n * @description\n *\n * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful\n * mocks to the {@link AUTO.$injector $injector}.\n */\nangular.module('ngMock', ['ng']).provider({\n  $browser: angular.mock.$BrowserProvider,\n  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,\n  $log: angular.mock.$LogProvider,\n  $httpBackend: angular.mock.$HttpBackendProvider,\n  $rootElement: angular.mock.$RootElementProvider\n}).config(function($provide) {\n  $provide.decorator('$timeout', function($delegate, $browser) {\n    $delegate.flush = function() {\n      $browser.defer.flush();\n    };\n    return $delegate;\n  });\n});\n\n\n/**\n * @ngdoc overview\n * @name ngMockE2E\n * @description\n *\n * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.\n * Currently there is only one mock present in this module -\n * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.\n */\nangular.module('ngMockE2E', ['ng']).config(function($provide) {\n  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);\n});\n\n/**\n * @ngdoc object\n * @name ngMockE2E.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of\n * applications that use the {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for unit testing please see\n * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.\n *\n * This implementation can be used to respond with static or dynamic responses via the `when` api\n * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the\n * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch\n * templates from a webserver).\n *\n * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application\n * is being developed with the real backend api replaced with a mock, it is often desirable for\n * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch\n * templates or static files from the webserver). To configure the backend with this behavior\n * use the `passThrough` request handler of `when` instead of `respond`.\n *\n * Additionally, we don't want to manually have to flush mocked out requests like we do during unit\n * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests\n * automatically, closely simulating the behavior of the XMLHttpRequest object.\n *\n * To setup the application to run with this http backend, you have to create a module that depends\n * on the `ngMockE2E` and your application modules and defines the fake backend:\n *\n * <pre>\n *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);\n *   myAppDev.run(function($httpBackend) {\n *     phones = [{name: 'phone1'}, {name: 'phone2'}];\n *\n *     // returns the current list of phones\n *     $httpBackend.whenGET('/phones').respond(phones);\n *\n *     // adds a new phone to the phones array\n *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {\n *       phones.push(angular.fromJSON(data));\n *     });\n *     $httpBackend.whenGET(/^\\/templates\\//).passThrough();\n *     //...\n *   });\n * </pre>\n *\n * Afterwards, bootstrap your app with this new module.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#when\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition.\n *\n * @param {string} method HTTP method.\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n *   object and returns true if the headers match the current definition.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n *\n *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n *    – The respond method takes a set of static data to be returned or a function that can return\n *    an array containing response status (number), response data (string) and response headers\n *    (Object).\n *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`\n *    handler, will be pass through to the real backend (an XHR request will be made to the\n *    server.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenGET\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for GET requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenHEAD\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for HEAD requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenDELETE\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for DELETE requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPOST\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for POST requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPUT\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PUT requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPATCH\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PATCH requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenJSONP\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for JSONP requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\nangular.mock.e2e = {};\nangular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];\n\n\nangular.mock.clearDataCache = function() {\n  var key,\n      cache = angular.element.cache;\n\n  for(key in cache) {\n    if (cache.hasOwnProperty(key)) {\n      var handle = cache[key].handle;\n\n      handle && angular.element(handle.elem).unbind();\n      delete cache[key];\n    }\n  }\n};\n\n\nwindow.jstestdriver && (function(window) {\n  /**\n   * Global method to output any number of objects into JSTD console. Useful for debugging.\n   */\n  window.dump = function() {\n    var args = [];\n    angular.forEach(arguments, function(arg) {\n      args.push(angular.mock.dump(arg));\n    });\n    jstestdriver.console.log.apply(jstestdriver.console, args);\n    if (window.console) {\n      window.console.log.apply(window.console, args);\n    }\n  };\n})(window);\n\n\nwindow.jasmine && (function(window) {\n\n  afterEach(function() {\n    var spec = getCurrentSpec();\n    var injector = spec.$injector;\n\n    spec.$injector = null;\n    spec.$modules = null;\n\n    if (injector) {\n      injector.get('$rootElement').unbind();\n      injector.get('$browser').pollFns.length = 0;\n    }\n\n    angular.mock.clearDataCache();\n\n    // clean up jquery's fragment cache\n    angular.forEach(angular.element.fragments, function(val, key) {\n      delete angular.element.fragments[key];\n    });\n\n    MockXhr.$$lastInstance = null;\n\n    angular.forEach(angular.callbacks, function(val, key) {\n      delete angular.callbacks[key];\n    });\n    angular.callbacks.counter = 0;\n  });\n\n  function getCurrentSpec() {\n    return jasmine.getEnv().currentSpec;\n  }\n\n  function isSpecRunning() {\n    var spec = getCurrentSpec();\n    return spec && spec.queue.running;\n  }\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.module\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * This function registers a module configuration code. It collects the configuration information\n   * which will be used when the injector is created by {@link angular.mock.inject inject}.\n   *\n   * See {@link angular.mock.inject inject} for usage example\n   *\n   * @param {...(string|Function)} fns any number of modules which are represented as string\n   *        aliases or as anonymous module initialization functions. The modules are used to\n   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.\n   */\n  window.module = angular.mock.module = function() {\n    var moduleFns = Array.prototype.slice.call(arguments, 0);\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      if (spec.$injector) {\n        throw Error('Injector already created, can not register a module!');\n      } else {\n        var modules = spec.$modules || (spec.$modules = []);\n        angular.forEach(moduleFns, function(module) {\n          modules.push(module);\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.inject\n   * @description\n   *\n   * *NOTE*: This is function is also published on window for easy access.<br>\n   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.\n   *\n   * The inject function wraps a function into an injectable function. The inject() creates new\n   * instance of {@link AUTO.$injector $injector} per test, which is then used for\n   * resolving references.\n   *\n   * See also {@link angular.mock.module module}\n   *\n   * Example of what a typical jasmine tests looks like with the inject method.\n   * <pre>\n   *\n   *   angular.module('myApplicationModule', [])\n   *       .value('mode', 'app')\n   *       .value('version', 'v1.0.1');\n   *\n   *\n   *   describe('MyApp', function() {\n   *\n   *     // You need to load modules that you want to test,\n   *     // it loads only the \"ng\" module by default.\n   *     beforeEach(module('myApplicationModule'));\n   *\n   *\n   *     // inject() is used to inject arguments of all given functions\n   *     it('should provide a version', inject(function(mode, version) {\n   *       expect(version).toEqual('v1.0.1');\n   *       expect(mode).toEqual('app');\n   *     }));\n   *\n   *\n   *     // The inject and module method can also be used inside of the it or beforeEach\n   *     it('should override a version and test the new version is injected', function() {\n   *       // module() takes functions or strings (module aliases)\n   *       module(function($provide) {\n   *         $provide.value('version', 'overridden'); // override version here\n   *       });\n   *\n   *       inject(function(version) {\n   *         expect(version).toEqual('overridden');\n   *       });\n   *     ));\n   *   });\n   *\n   * </pre>\n   *\n   * @param {...Function} fns any number of functions which will be injected using the injector.\n   */\n  window.inject = angular.mock.inject = function() {\n    var blockFns = Array.prototype.slice.call(arguments, 0);\n    var errorForStack = new Error('Declaration Location');\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      var spec = getCurrentSpec();\n      var modules = spec.$modules || [];\n      modules.unshift('ngMock');\n      modules.unshift('ng');\n      var injector = spec.$injector;\n      if (!injector) {\n        injector = spec.$injector = angular.injector(modules);\n      }\n      for(var i = 0, ii = blockFns.length; i < ii; i++) {\n        try {\n          injector.invoke(blockFns[i] || angular.noop, this);\n        } catch (e) {\n          if(e.stack) e.stack +=  '\\n' + errorForStack.stack;\n          throw e;\n        } finally {\n          errorForStack = null;\n        }\n      }\n    }\n  };\n})(window);\n"
  },
  {
    "path": "chapter6/recipe4/test/lib/angular/angular-scenario.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Mar 21 12:46:34 2012 -0700\n */\n(function( window, undefined ) {\n'use strict';\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.7.2\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in array && array[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n\t\tvar exec,\n\t\t\tbulk = key == null,\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\n\t\t// Sets many values\n\t\tif ( key && typeof key === \"object\" ) {\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n\t\t\t}\n\t\t\tchainable = 1;\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = pass === undefined && jQuery.isFunction( value );\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations only iterate when executing function values\n\t\t\t\tif ( exec ) {\n\t\t\t\t\texec = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn exec.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\n\t\t\t\t// Otherwise they run against the entire set\n\t\t\t\t} else {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor (; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchainable = 1;\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfired = true;\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar length = list.length;\n\t\t\t\t\tadd( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory || memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tfragment,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tpixelMargin: true\n\t};\n\n\t// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead\n\tjQuery.boxModel = support.boxModel = (document.compatMode === \"CSS1Compat\");\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor ( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\tfragment.removeChild( div );\n\n\t// Null elements to avoid leaks in IE\n\tfragment = select = opt = div = input = null;\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tmarginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,\n\t\t\tpaddingMarginBorderVisibility, paddingMarginBorder,\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tconMarginTop = 1;\n\t\tpaddingMarginBorder = \"padding:0;margin:0;border:\";\n\t\tpositionTopLeftWidthHeight = \"position:absolute;top:0;left:0;width:1px;height:1px;\";\n\t\tpaddingMarginBorderVisibility = paddingMarginBorder + \"0;visibility:hidden;\";\n\t\tstyle = \"style='\" + positionTopLeftWidthHeight + paddingMarginBorder + \"5px solid #000;\";\n\t\thtml = \"<div \" + style + \"display:block;'><div style='\" + paddingMarginBorder + \"0;display:block;overflow:hidden;'></div></div>\" +\n\t\t\t\"<table \" + style + \"' cellpadding='0' cellspacing='0'>\" +\n\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = paddingMarginBorderVisibility + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td style='\" + paddingMarginBorder + \"0;display:none'></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName( \"td\" );\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t// gets computed margin-right based on width of container. For more\n\t\t// info see bug #3333\n\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tmarginDiv = document.createElement( \"div\" );\n\t\t\tmarginDiv.style.width = \"0\";\n\t\t\tmarginDiv.style.marginRight = \"0\";\n\t\t\tdiv.style.width = \"2px\";\n\t\t\tdiv.appendChild( marginDiv );\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\t// (IE < 8 does this)\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.width = div.style.padding = \"1px\";\n\t\t\tdiv.style.border = 0;\n\t\t\tdiv.style.overflow = \"hidden\";\n\t\t\tdiv.style.display = \"inline\";\n\t\t\tdiv.style.zoom = 1;\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.style.overflow = \"visible\";\n\t\t\tdiv.innerHTML = \"<div style='width:5px;'></div>\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\t\t}\n\n\t\tdiv.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;\n\t\tdiv.innerHTML = html;\n\n\t\touter = div.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.style.marginTop = \"1%\";\n\t\t\tsupport.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== \"1%\";\n\t\t}\n\n\t\tif ( typeof container.style.zoom !== \"undefined\" ) {\n\t\t\tcontainer.style.zoom = 1;\n\t\t}\n\n\t\tbody.removeChild( container );\n\t\tmarginDiv = div = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\treturn support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ internalKey ] : internalKey;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ internalKey ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( internalKey );\n\t\t\t} else {\n\t\t\t\telem[ internalKey ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, part, attr, name, l,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = elem.attributes;\n\t\t\t\t\tfor ( l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split( \".\", 2 );\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\t\tpart = parts[1] + \"!\";\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\tdata = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\tif ( data === undefined && elem ) {\n\t\t\t\t\tdata = jQuery.data( elem, key );\n\t\t\t\t\tdata = dataAttr( elem, key, data );\n\t\t\t\t}\n\n\t\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\t\tdata;\n\t\t\t}\n\n\t\t\tparts[1] = value;\n\t\t\tthis.each(function() {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.triggerHandler( \"setData\" + part, parts );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + part, parts );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, false );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\thooks = {};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( object );\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, l, isBool,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\t\t\tattrNames = value.toLowerCase().split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tisBool = rboolean.test( name );\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\t// Do not do this for boolean attributes (see #10870)\n\t\t\t\t\tif ( !isBool ) {\n\t\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\t}\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( isBool && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true,\n\t\tcoords: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = \"\" + value );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+)?\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\tvar attrs = elem.attributes || {};\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || (attrs.id || {}).value === m[2]) &&\n\t\t\t(!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tquick: selector && quickParse( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t ( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\told = null;\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\tspecial = jQuery.event.special[ event.type ] || {},\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n\t\t\t// Pregenerate a single jQuery object for reuse with .is()\n\t\t\tjqcur = jQuery(this);\n\t\t\tjqcur.context = this.ownerDocument || this;\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process events on disabled elements (#6911, #8165)\n\t\t\t\tif ( cur.disabled !== true ) {\n\t\t\t\t\tselMatch = {};\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tjqcur[0] = cur;\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\t\tselMatch[ sel ] = (\n\t\t\t\t\t\t\t\thandleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\tret;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\t\t\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\telem._change_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) { // && selector != null\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( var type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\n\t\t\tparts.push( m[1] );\n\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\t\t/* falls through */\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n// Expose origPOS\n// \"global\" as in regardless of relation to brackets/parens\nExpr.match.globalPOS = origPOS;\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry {\n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.globalPOS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\tPOS.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery.clean(arguments) );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tnull;\n\t\t\t}\n\n\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, function( i, elem ) {\n\t\t\t\t\tif ( elem.src ) {\n\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\turl: elem.src,\n\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\tdataType: \"script\"\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\n\t// IE blanks contents when cloning scripts\n\t} else if ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdest.text = src.text;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n\n\t// Clear flags for bubbling special change/submit events, they must\n\t// be reattached when the newly cloned events are first activated\n\tdest.removeAttribute( \"_submit_attached\" );\n\tdest.removeAttribute( \"_change_attached\" );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n\t// Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n\tvar div = document.createElement( \"div\" );\n\tsafeFragment.appendChild( div );\n\n\tdiv.innerHTML = elem.outerHTML;\n\treturn div.firstChild;\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t\tclone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ?\n\t\t\t\telem.cloneNode( true ) :\n\t\t\t\tshimCloneNode( elem );\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType, script, j,\n\t\t\t\tret = [];\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\"),\n\t\t\t\t\t\tsafeChildNodes = safeFragment.childNodes,\n\t\t\t\t\t\tremove;\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\n\t\t\t\t\t// Clear elements from DocumentFragment (safeFragment or otherwise)\n\t\t\t\t\t// to avoid hoarding elements. Fixes #11356\n\t\t\t\t\tif ( div ) {\n\t\t\t\t\t\tdiv.parentNode.removeChild( div );\n\n\t\t\t\t\t\t// Guard against -1 index exceptions in FF3.6\n\t\t\t\t\t\tif ( safeChildNodes.length > 0 ) {\n\t\t\t\t\t\t\tremove = safeChildNodes[ safeChildNodes.length - 1 ];\n\n\t\t\t\t\t\t\tif ( remove && remove.parentNode ) {\n\t\t\t\t\t\t\t\tremove.parentNode.removeChild( remove );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tscript = ret[i];\n\t\t\t\tif ( scripts && jQuery.nodeName( script, \"script\" ) && (!script.type || rscriptType.test( script.type )) ) {\n\t\t\t\t\tscripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( script.nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( script.getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( script );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnum = /^[\\-+]?(?:\\d*\\.)?\\d+$/i,\n\trnumnonpx = /^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\trmargin = /^margin/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\n\t// order is important!\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\treturn jQuery.access( this, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t}, name, value, arguments.length > 1 );\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {},\n\t\t\tret, name;\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// DEPRECATED in 1.3, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle, width,\n\t\t\tstyle = elem.style;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( (defaultView = elem.ownerDocument.defaultView) &&\n\t\t\t\t(computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// WebKit uses \"computed value (percentage if specified)\" instead of \"used value\" for margins\n\t\t// which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {\n\t\t\twidth = style.width;\n\t\t\tstyle.width = ret;\n\t\t\tret = computedStyle.width;\n\t\t\tstyle.width = width;\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( rnumnonpx.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\ti = name === \"width\" ? 1 : 0,\n\t\tlen = 4;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tfor ( ; i < len; i += 2 ) {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ];\n\t}\n\n\t// Computed unit is not pixels. Stop here and return.\n\tif ( rnumnonpx.test(val) ) {\n\t\treturn val;\n\t}\n\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tfor ( ; i < len; i += 2 ) {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val + \"px\";\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\treturn jQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\treturn rnum.test( value ) ?\n\t\t\t\tvalue + \"px\" :\n\t\t\t\tvalue;\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\treturn curCSS( elem, \"margin-right\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i,\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n\t\t\t\texpanded = {};\n\n\t\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n});\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = ( typeof s.data === \"string\" ) && /^application\\/x\\-www\\-form\\-urlencoded/.test( s.contentType );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t} catch( _ ) {\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( (display === \"\" && jQuery.css(elem, \"display\") === \"none\") ||\n\t\t\t\t\t\t!jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e, hooks, replace,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\t// first pass over propertys to expand / normalize\n\t\t\tfor ( p in prop ) {\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tif ( ( hooks = jQuery.cssHooks[ name ] ) && \"expand\" in hooks ) {\n\t\t\t\t\treplace = hooks.expand( prop[ name ] );\n\t\t\t\t\tdelete prop[ name ];\n\n\t\t\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t\t\t// also - reusing 'p' from above because we have the correct \"name\"\n\t\t\t\t\tfor ( p in replace ) {\n\t\t\t\t\t\tif ( ! ( p in prop ) ) {\n\t\t\t\t\t\t\tprop[ p ] = replace[ p ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( name in prop ) {\n\t\t\t\tval = prop[ name ];\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, index ) {\n\t\t\t\tvar hooks = data[ index ];\n\t\t\t\tjQuery.removeData( elem, index, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n\t\t\t\tstopQueue( this, data, index );\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ index ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ index ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p ) {\n\t\t\treturn p;\n\t\t},\n\t\tswing: function( p ) {\n\t\t\treturn ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tif ( self.options.hide ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t\t} else if ( self.options.show ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.end );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Ensure props that can't be negative don't go there on undershoot easing\njQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {\n\t// exclude marginTop, marginLeft, marginBottom and marginRight from this list\n\tif ( prop.indexOf( \"margin\" ) ) {\n\t\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( jQuery.support.boxModel ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar getOffset,\n\trtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tgetOffset = function( elem, doc, docElem, box ) {\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow( doc ),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tgetOffset = function( elem, doc, docElem ) {\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar elem = this[0],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn null;\n\t}\n\n\tif ( elem === doc.body ) {\n\t\treturn jQuery.offset.bodyOffset( elem );\n\t}\n\n\treturn getOffset( elem, doc, doc.documentElement );\n};\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t top ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tvar clientProp = \"client\" + name,\n\t\tscrollProp = \"scroll\" + name,\n\t\toffsetProp = \"offset\" + name;\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( value ) {\n\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\tvar doc, docElemProp, orig, ret;\n\n\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\t\tdoc = elem.document;\n\t\t\t\tdocElemProp = doc.documentElement[ clientProp ];\n\t\t\t\treturn jQuery.support.boxModel && docElemProp ||\n\t\t\t\t\tdoc.body && doc.body[ clientProp ] || docElemProp;\n\t\t\t}\n\n\t\t\t// Get document width or height\n\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t// when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]\n\t\t\t\t// so we can't use max, as it'll choose the incorrect offset[Width/Height]\n\t\t\t\t// instead we use the correct client[Width/Height]\n\t\t\t\t// support:IE6\n\t\t\t\tif ( doc[ clientProp ] >= doc[ scrollProp ] ) {\n\t\t\t\t\treturn doc[ clientProp ];\n\t\t\t\t}\n\n\t\t\t\treturn Math.max(\n\t\t\t\t\telem.body[ scrollProp ], doc[ scrollProp ],\n\t\t\t\t\telem.body[ offsetProp ], doc[ offsetProp ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get width or height on the element\n\t\t\tif ( value === undefined ) {\n\t\t\t\torig = jQuery.css( elem, type );\n\t\t\t\tret = parseFloat( orig );\n\t\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\t\t\t}\n\n\t\t\t// Set the width or height on the element\n\t\t\tjQuery( elem ).css( type, value );\n\t\t}, type, value, arguments.length, null );\n\t};\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );\n/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document){\n  var _jQuery = window.jQuery.noConflict(true);\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n\n/**\n * Setup file for the Scenario.\n * Must be first in the compilation/bootstrap list.\n */\n\n// Public namespace\nangular.scenario = angular.scenario || {};\n\n/**\n * Defines a new output format.\n *\n * @param {string} name the name of the new output format\n * @param {function()} fn function(context, runner) that generates the output\n */\nangular.scenario.output = angular.scenario.output || function(name, fn) {\n  angular.scenario.output[name] = fn;\n};\n\n/**\n * Defines a new DSL statement. If your factory function returns a Future\n * it's returned, otherwise the result is assumed to be a map of functions\n * for chaining. Chained functions are subject to the same rules.\n *\n * Note: All functions on the chain are bound to the chain scope so values\n *   set on \"this\" in your statement function are available in the chained\n *   functions.\n *\n * @param {string} name The name of the statement\n * @param {function()} fn Factory function(), return a function for\n *  the statement.\n */\nangular.scenario.dsl = angular.scenario.dsl || function(name, fn) {\n  angular.scenario.dsl[name] = function() {\n    function executeStatement(statement, args) {\n      var result = statement.apply(this, args);\n      if (angular.isFunction(result) || result instanceof angular.scenario.Future)\n        return result;\n      var self = this;\n      var chain = angular.extend({}, result);\n      angular.forEach(chain, function(value, name) {\n        if (angular.isFunction(value)) {\n          chain[name] = function() {\n            return executeStatement.call(self, value, arguments);\n          };\n        } else {\n          chain[name] = value;\n        }\n      });\n      return chain;\n    }\n    var statement = fn.apply(this, arguments);\n    return function() {\n      return executeStatement.call(this, statement, arguments);\n    };\n  };\n};\n\n/**\n * Defines a new matcher for use with the expects() statement. The value\n * this.actual (like in Jasmine) is available in your matcher to compare\n * against. Your function should return a boolean. The future is automatically\n * created for you.\n *\n * @param {string} name The name of the matcher\n * @param {function()} fn The matching function(expected).\n */\nangular.scenario.matcher = angular.scenario.matcher || function(name, fn) {\n  angular.scenario.matcher[name] = function(expected) {\n    var prefix = 'expect ' + this.future.name + ' ';\n    if (this.inverse) {\n      prefix += 'not ';\n    }\n    var self = this;\n    this.addFuture(prefix + name + ' ' + angular.toJson(expected),\n      function(done) {\n        var error;\n        self.actual = self.future.value;\n        if ((self.inverse && fn.call(self, expected)) ||\n            (!self.inverse && !fn.call(self, expected))) {\n          error = 'expected ' + angular.toJson(expected) +\n            ' but was ' + angular.toJson(self.actual);\n        }\n        done(error);\n    });\n  };\n};\n\n/**\n * Initialize the scenario runner and run !\n *\n * Access global window and document object\n * Access $runner through closure\n *\n * @param {Object=} config Config options\n */\nangular.scenario.setUpAndRun = function(config) {\n  var href = window.location.href;\n  var body = _jQuery(document.body);\n  var output = [];\n  var objModel = new angular.scenario.ObjectModel($runner);\n\n  if (config && config.scenario_output) {\n    output = config.scenario_output.split(',');\n  }\n\n  angular.forEach(angular.scenario.output, function(fn, name) {\n    if (!output.length || indexOf(output,name) != -1) {\n      var context = body.append('<div></div>').find('div:last');\n      context.attr('id', name);\n      fn.call({}, context, $runner, objModel);\n    }\n  });\n\n  if (!/^http/.test(href) && !/^https/.test(href)) {\n    body.append('<p id=\"system-error\"></p>');\n    body.find('#system-error').text(\n      'Scenario runner must be run using http or https. The protocol ' +\n      href.split(':')[0] + ':// is not supported.'\n    );\n    return;\n  }\n\n  var appFrame = body.append('<div id=\"application\"></div>').find('#application');\n  var application = new angular.scenario.Application(appFrame);\n\n  $runner.on('RunnerEnd', function() {\n    appFrame.css('display', 'none');\n    appFrame.find('iframe').attr('src', 'about:blank');\n  });\n\n  $runner.on('RunnerError', function(error) {\n    if (window.console) {\n      console.log(formatException(error));\n    } else {\n      // Do something for IE\n      alert(error);\n    }\n  });\n\n  $runner.run(application);\n};\n\n/**\n * Iterates through list with iterator function that must call the\n * continueFunction to continute iterating.\n *\n * @param {Array} list list to iterate over\n * @param {function()} iterator Callback function(value, continueFunction)\n * @param {function()} done Callback function(error, result) called when\n *   iteration finishes or an error occurs.\n */\nfunction asyncForEach(list, iterator, done) {\n  var i = 0;\n  function loop(error, index) {\n    if (index && index > i) {\n      i = index;\n    }\n    if (error || i >= list.length) {\n      done(error);\n    } else {\n      try {\n        iterator(list[i++], loop);\n      } catch (e) {\n        done(e);\n      }\n    }\n  }\n  loop();\n}\n\n/**\n * Formats an exception into a string with the stack trace, but limits\n * to a specific line length.\n *\n * @param {Object} error The exception to format, can be anything throwable\n * @param {Number=} [maxStackLines=5] max lines of the stack trace to include\n *  default is 5.\n */\nfunction formatException(error, maxStackLines) {\n  maxStackLines = maxStackLines || 5;\n  var message = error.toString();\n  if (error.stack) {\n    var stack = error.stack.split('\\n');\n    if (stack[0].indexOf(message) === -1) {\n      maxStackLines++;\n      stack.unshift(error.message);\n    }\n    message = stack.slice(0, maxStackLines).join('\\n');\n  }\n  return message;\n}\n\n/**\n * Returns a function that gets the file name and line number from a\n * location in the stack if available based on the call site.\n *\n * Note: this returns another function because accessing .stack is very\n * expensive in Chrome.\n *\n * @param {Number} offset Number of stack lines to skip\n */\nfunction callerFile(offset) {\n  var error = new Error();\n\n  return function() {\n    var line = (error.stack || '').split('\\n')[offset];\n\n    // Clean up the stack trace line\n    if (line) {\n      if (line.indexOf('@') !== -1) {\n        // Firefox\n        line = line.substring(line.indexOf('@')+1);\n      } else {\n        // Chrome\n        line = line.substring(line.indexOf('(')+1).replace(')', '');\n      }\n    }\n\n    return line || '';\n  };\n}\n\n/**\n * Triggers a browser event. Attempts to choose the right event if one is\n * not specified.\n *\n * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement\n * @param {string} type Optional event type.\n * @param {Array.<string>=} keys Optional list of pressed keys\n *        (valid values: 'alt', 'meta', 'shift', 'ctrl')\n */\nfunction browserTrigger(element, type, keys) {\n  if (element && !element.nodeName) element = element[0];\n  if (!element) return;\n  if (!type) {\n    type = {\n        'text':            'change',\n        'textarea':        'change',\n        'hidden':          'change',\n        'password':        'change',\n        'button':          'click',\n        'submit':          'click',\n        'reset':           'click',\n        'image':           'click',\n        'checkbox':        'click',\n        'radio':           'click',\n        'select-one':      'change',\n        'select-multiple': 'change'\n    }[lowercase(element.type)] || 'click';\n  }\n  if (lowercase(nodeName_(element)) == 'option') {\n    element.parentNode.value = element.value;\n    element = element.parentNode;\n    type = 'change';\n  }\n\n  keys = keys || [];\n  function pressed(key) {\n    return indexOf(keys, key) !== -1;\n  }\n\n  if (msie < 9) {\n    switch(element.type) {\n      case 'radio':\n      case 'checkbox':\n        element.checked = !element.checked;\n        break;\n    }\n    // WTF!!! Error: Unspecified error.\n    // Don't know why, but some elements when detached seem to be in inconsistent state and\n    // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)\n    // forcing the browser to compute the element position (by reading its CSS)\n    // puts the element in consistent state.\n    element.style.posLeft;\n\n    // TODO(vojta): create event objects with pressed keys to get it working on IE<9\n    var ret = element.fireEvent('on' + type);\n    if (lowercase(element.type) == 'submit') {\n      while(element) {\n        if (lowercase(element.nodeName) == 'form') {\n          element.fireEvent('onsubmit');\n          break;\n        }\n        element = element.parentNode;\n      }\n    }\n    return ret;\n  } else {\n    var evnt = document.createEvent('MouseEvents'),\n        originalPreventDefault = evnt.preventDefault,\n        iframe = _jQuery('#application iframe')[0],\n        appWindow = iframe ? iframe.contentWindow : window,\n        fakeProcessDefault = true,\n        finalProcessDefault,\n        angular = appWindow.angular || {};\n\n    // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208\n    angular['ff-684208-preventDefault'] = false;\n    evnt.preventDefault = function() {\n      fakeProcessDefault = false;\n      return originalPreventDefault.apply(evnt, arguments);\n    };\n\n    evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, pressed('ctrl'), pressed('alt'),\n                        pressed('shift'), pressed('meta'), 0, element);\n\n    element.dispatchEvent(evnt);\n    finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);\n\n    delete angular['ff-684208-preventDefault'];\n\n    return finalProcessDefault;\n  }\n}\n\n/**\n * Don't use the jQuery trigger method since it works incorrectly.\n *\n * jQuery notifies listeners and then changes the state of a checkbox and\n * does not create a real browser event. A real click changes the state of\n * the checkbox and then notifies listeners.\n *\n * To work around this we instead use our own handler that fires a real event.\n */\n(function(fn){\n  var parentTrigger = fn.trigger;\n  fn.trigger = function(type) {\n    if (/(click|change|keydown|blur|input)/.test(type)) {\n      var processDefaults = [];\n      this.each(function(index, node) {\n        processDefaults.push(browserTrigger(node, type));\n      });\n\n      // this is not compatible with jQuery - we return an array of returned values,\n      // so that scenario runner know whether JS code has preventDefault() of the event or not...\n      return processDefaults;\n    }\n    return parentTrigger.apply(this, arguments);\n  };\n})(_jQuery.fn);\n\n/**\n * Finds all bindings with the substring match of name and returns an\n * array of their values.\n *\n * @param {string} bindExp The name to match\n * @return {Array.<string>} String of binding values\n */\n_jQuery.fn.bindings = function(windowJquery, bindExp) {\n  var result = [], match,\n      bindSelector = '.ng-binding:visible';\n  if (angular.isString(bindExp)) {\n    bindExp = bindExp.replace(/\\s/g, '');\n    match = function (actualExp) {\n      if (actualExp) {\n        actualExp = actualExp.replace(/\\s/g, '');\n        if (actualExp == bindExp) return true;\n        if (actualExp.indexOf(bindExp) == 0) {\n          return actualExp.charAt(bindExp.length) == '|';\n        }\n      }\n    }\n  } else if (bindExp) {\n    match = function(actualExp) {\n      return actualExp && bindExp.exec(actualExp);\n    }\n  } else {\n    match = function(actualExp) {\n      return !!actualExp;\n    };\n  }\n  var selection = this.find(bindSelector);\n  if (this.is(bindSelector)) {\n    selection = selection.add(this);\n  }\n\n  function push(value) {\n    if (value == undefined) {\n      value = '';\n    } else if (typeof value != 'string') {\n      value = angular.toJson(value);\n    }\n    result.push('' + value);\n  }\n\n  selection.each(function() {\n    var element = windowJquery(this),\n        binding;\n    if (binding = element.data('$binding')) {\n      if (typeof binding == 'string') {\n        if (match(binding)) {\n          push(element.scope().$eval(binding));\n        }\n      } else {\n        if (!angular.isArray(binding)) {\n          binding = [binding];\n        }\n        for(var fns, j=0, jj=binding.length;  j<jj; j++) {\n          fns = binding[j];\n          if (fns.parts) {\n            fns = fns.parts;\n          } else {\n            fns = [fns];\n          }\n          for (var scope, fn, i = 0, ii = fns.length; i < ii; i++) {\n            if(match((fn = fns[i]).exp)) {\n              push(fn(scope = scope || element.scope()));\n            }\n          }\n        }\n      }\n    }\n  });\n  return result;\n};\n\n/**\n * Represents the application currently being tested and abstracts usage\n * of iframes or separate windows.\n *\n * @param {Object} context jQuery wrapper around HTML context.\n */\nangular.scenario.Application = function(context) {\n  this.context = context;\n  context.append(\n    '<h2>Current URL: <a href=\"about:blank\">None</a></h2>' +\n    '<div id=\"test-frames\"></div>'\n  );\n};\n\n/**\n * Gets the jQuery collection of frames. Don't use this directly because\n * frames may go stale.\n *\n * @private\n * @return {Object} jQuery collection\n */\nangular.scenario.Application.prototype.getFrame_ = function() {\n  return this.context.find('#test-frames iframe:last');\n};\n\n/**\n * Gets the window of the test runner frame. Always favor executeAction()\n * instead of this method since it prevents you from getting a stale window.\n *\n * @private\n * @return {Object} the window of the frame\n */\nangular.scenario.Application.prototype.getWindow_ = function() {\n  var contentWindow = this.getFrame_().prop('contentWindow');\n  if (!contentWindow)\n    throw 'Frame window is not accessible.';\n  return contentWindow;\n};\n\n/**\n * Changes the location of the frame.\n *\n * @param {string} url The URL. If it begins with a # then only the\n *   hash of the page is changed.\n * @param {function()} loadFn function($window, $document) Called when frame loads.\n * @param {function()} errorFn function(error) Called if any error when loading.\n */\nangular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorFn) {\n  var self = this;\n  var frame = this.getFrame_();\n  //TODO(esprehn): Refactor to use rethrow()\n  errorFn = errorFn || function(e) { throw e; };\n  if (url === 'about:blank') {\n    errorFn('Sandbox Error: Navigating to about:blank is not allowed.');\n  } else if (url.charAt(0) === '#') {\n    url = frame.attr('src').split('#')[0] + url;\n    frame.attr('src', url);\n    this.executeAction(loadFn);\n  } else {\n    frame.remove();\n    this.context.find('#test-frames').append('<iframe>');\n    frame = this.getFrame_();\n    frame.load(function() {\n      frame.unbind();\n      try {\n        self.executeAction(loadFn);\n      } catch (e) {\n        errorFn(e);\n      }\n    }).attr('src', url);\n  }\n  this.context.find('> h2 a').attr('href', url).text(url);\n};\n\n/**\n * Executes a function in the context of the tested application. Will wait\n * for all pending angular xhr requests before executing.\n *\n * @param {function()} action The callback to execute. function($window, $document)\n *  $document is a jQuery wrapped document.\n */\nangular.scenario.Application.prototype.executeAction = function(action) {\n  var self = this;\n  var $window = this.getWindow_();\n  if (!$window.document) {\n    throw 'Sandbox Error: Application document not accessible.';\n  }\n  if (!$window.angular) {\n    return action.call(this, $window, _jQuery($window.document));\n  }\n  angularInit($window.document, function(element) {\n    var $injector = $window.angular.element(element).injector();\n    var $element = _jQuery(element);\n\n    $element.injector = function() {\n      return $injector;\n    };\n\n    $injector.invoke(function($browser){\n      $browser.notifyWhenNoOutstandingRequests(function() {\n        action.call(self, $window, $element);\n      });\n    });\n  });\n};\n\n/**\n * The representation of define blocks. Don't used directly, instead use\n * define() in your tests.\n *\n * @param {string} descName Name of the block\n * @param {Object} parent describe or undefined if the root.\n */\nangular.scenario.Describe = function(descName, parent) {\n  this.only = parent && parent.only;\n  this.beforeEachFns = [];\n  this.afterEachFns = [];\n  this.its = [];\n  this.children = [];\n  this.name = descName;\n  this.parent = parent;\n  this.id = angular.scenario.Describe.id++;\n\n  /**\n   * Calls all before functions.\n   */\n  var beforeEachFns = this.beforeEachFns;\n  this.setupBefore = function() {\n    if (parent) parent.setupBefore.call(this);\n    angular.forEach(beforeEachFns, function(fn) { fn.call(this); }, this);\n  };\n\n  /**\n   * Calls all after functions.\n   */\n  var afterEachFns = this.afterEachFns;\n  this.setupAfter  = function() {\n    angular.forEach(afterEachFns, function(fn) { fn.call(this); }, this);\n    if (parent) parent.setupAfter.call(this);\n  };\n};\n\n// Shared Unique ID generator for every describe block\nangular.scenario.Describe.id = 0;\n\n// Shared Unique ID generator for every it (spec)\nangular.scenario.Describe.specId = 0;\n\n/**\n * Defines a block to execute before each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.beforeEach = function(body) {\n  this.beforeEachFns.push(body);\n};\n\n/**\n * Defines a block to execute after each it or nested describe.\n *\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.afterEach = function(body) {\n  this.afterEachFns.push(body);\n};\n\n/**\n * Creates a new describe block that's a child of this one.\n *\n * @param {string} name Name of the block. Appended to the parent block's name.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.describe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Same as describe() but makes ddescribe blocks the only to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.ddescribe = function(name, body) {\n  var child = new angular.scenario.Describe(name, this);\n  child.only = true;\n  this.children.push(child);\n  body.call(child);\n};\n\n/**\n * Use to disable a describe block.\n */\nangular.scenario.Describe.prototype.xdescribe = angular.noop;\n\n/**\n * Defines a test.\n *\n * @param {string} name Name of the test.\n * @param {function()} vody Body of the block.\n */\nangular.scenario.Describe.prototype.it = function(name, body) {\n  this.its.push({\n    id: angular.scenario.Describe.specId++,\n    definition: this,\n    only: this.only,\n    name: name,\n    before: this.setupBefore,\n    body: body,\n    after: this.setupAfter\n  });\n};\n\n/**\n * Same as it() but makes iit tests the only test to run.\n *\n * @param {string} name Name of the test.\n * @param {function()} body Body of the block.\n */\nangular.scenario.Describe.prototype.iit = function(name, body) {\n  this.it.apply(this, arguments);\n  this.its[this.its.length-1].only = true;\n};\n\n/**\n * Use to disable a test block.\n */\nangular.scenario.Describe.prototype.xit = angular.noop;\n\n/**\n * Gets an array of functions representing all the tests (recursively).\n * that can be executed with SpecRunner's.\n *\n * @return {Array<Object>} Array of it blocks {\n *   definition : Object // parent Describe\n *   only: boolean\n *   name: string\n *   before: Function\n *   body: Function\n *   after: Function\n *  }\n */\nangular.scenario.Describe.prototype.getSpecs = function() {\n  var specs = arguments[0] || [];\n  angular.forEach(this.children, function(child) {\n    child.getSpecs(specs);\n  });\n  angular.forEach(this.its, function(it) {\n    specs.push(it);\n  });\n  var only = [];\n  angular.forEach(specs, function(it) {\n    if (it.only) {\n      only.push(it);\n    }\n  });\n  return (only.length && only) || specs;\n};\n\n/**\n * A future action in a spec.\n *\n * @param {string} name of the future action\n * @param {function()} future callback(error, result)\n * @param {function()} Optional. function that returns the file/line number.\n */\nangular.scenario.Future = function(name, behavior, line) {\n  this.name = name;\n  this.behavior = behavior;\n  this.fulfilled = false;\n  this.value = undefined;\n  this.parser = angular.identity;\n  this.line = line || function() { return ''; };\n};\n\n/**\n * Executes the behavior of the closure.\n *\n * @param {function()} doneFn Callback function(error, result)\n */\nangular.scenario.Future.prototype.execute = function(doneFn) {\n  var self = this;\n  this.behavior(function(error, result) {\n    self.fulfilled = true;\n    if (result) {\n      try {\n        result = self.parser(result);\n      } catch(e) {\n        error = e;\n      }\n    }\n    self.value = error || result;\n    doneFn(error, result);\n  });\n};\n\n/**\n * Configures the future to convert it's final with a function fn(value)\n *\n * @param {function()} fn function(value) that returns the parsed value\n */\nangular.scenario.Future.prototype.parsedWith = function(fn) {\n  this.parser = fn;\n  return this;\n};\n\n/**\n * Configures the future to parse it's final value from JSON\n * into objects.\n */\nangular.scenario.Future.prototype.fromJson = function() {\n  return this.parsedWith(angular.fromJson);\n};\n\n/**\n * Configures the future to convert it's final value from objects\n * into JSON.\n */\nangular.scenario.Future.prototype.toJson = function() {\n  return this.parsedWith(angular.toJson);\n};\n\n/**\n * Maintains an object tree from the runner events.\n *\n * @param {Object} runner The scenario Runner instance to connect to.\n *\n * TODO(esprehn): Every output type creates one of these, but we probably\n *  want one global shared instance. Need to handle events better too\n *  so the HTML output doesn't need to do spec model.getSpec(spec.id)\n *  silliness.\n *\n * TODO(vojta) refactor on, emit methods (from all objects) - use inheritance\n */\nangular.scenario.ObjectModel = function(runner) {\n  var self = this;\n\n  this.specMap = {};\n  this.listeners = [];\n  this.value = {\n    name: '',\n    children: {}\n  };\n\n  runner.on('SpecBegin', function(spec) {\n    var block = self.value,\n        definitions = [];\n\n    angular.forEach(self.getDefinitionPath(spec), function(def) {\n      if (!block.children[def.name]) {\n        block.children[def.name] = {\n          id: def.id,\n          name: def.name,\n          children: {},\n          specs: {}\n        };\n      }\n      block = block.children[def.name];\n      definitions.push(def.name);\n    });\n\n    var it = self.specMap[spec.id] =\n             block.specs[spec.name] =\n             new angular.scenario.ObjectModel.Spec(spec.id, spec.name, definitions);\n\n    // forward the event\n    self.emit('SpecBegin', it);\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var it = self.getSpec(spec.id);\n    it.status = 'error';\n    it.error = error;\n\n    // forward the event\n    self.emit('SpecError', it, error);\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    complete(it);\n\n    // forward the event\n    self.emit('SpecEnd', it);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var it = self.getSpec(spec.id);\n    var step = new angular.scenario.ObjectModel.Step(step.name);\n    it.steps.push(step);\n\n    // forward the event\n    self.emit('StepBegin', it, step);\n  });\n\n  runner.on('StepEnd', function(spec) {\n    var it = self.getSpec(spec.id);\n    var step = it.getLastStep();\n    if (step.name !== step.name)\n      throw 'Events fired in the wrong order. Step names don\\'t match.';\n    complete(step);\n\n    // forward the event\n    self.emit('StepEnd', it, step);\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('failure', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepFailure', it, modelStep, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var it = self.getSpec(spec.id),\n        modelStep = it.getLastStep();\n\n    modelStep.setErrorStatus('error', error, step.line());\n    it.setStatusFromStep(modelStep);\n\n    // forward the event\n    self.emit('StepError', it, modelStep, error);\n  });\n\n  runner.on('RunnerBegin', function() {\n    self.emit('RunnerBegin');\n  });\n  runner.on('RunnerEnd', function() {\n    self.emit('RunnerEnd');\n  });\n\n  function complete(item) {\n    item.endTime = new Date().getTime();\n    item.duration = item.endTime - item.startTime;\n    item.status = item.status || 'success';\n  }\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName Name of the event to add a handler for\n * @param {function()} listener Function that will be called when event is fired\n */\nangular.scenario.ObjectModel.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.ObjectModel.prototype.emit = function(eventName) {\n  var self = this,\n      args = Array.prototype.slice.call(arguments, 1),\n      eventName = eventName.toLowerCase();\n\n  if (this.listeners[eventName]) {\n    angular.forEach(this.listeners[eventName], function(listener) {\n      listener.apply(self, args);\n    });\n  }\n};\n\n/**\n * Computes the path of definition describe blocks that wrap around\n * this spec.\n *\n * @param spec Spec to compute the path for.\n * @return {Array<Describe>} The describe block path\n */\nangular.scenario.ObjectModel.prototype.getDefinitionPath = function(spec) {\n  var path = [];\n  var currentDefinition = spec.definition;\n  while (currentDefinition && currentDefinition.name) {\n    path.unshift(currentDefinition);\n    currentDefinition = currentDefinition.parent;\n  }\n  return path;\n};\n\n/**\n * Gets a spec by id.\n *\n * @param {string} The id of the spec to get the object for.\n * @return {Object} the Spec instance\n */\nangular.scenario.ObjectModel.prototype.getSpec = function(id) {\n  return this.specMap[id];\n};\n\n/**\n * A single it block.\n *\n * @param {string} id Id of the spec\n * @param {string} name Name of the spec\n * @param {Array<string>=} definitionNames List of all describe block names that wrap this spec\n */\nangular.scenario.ObjectModel.Spec = function(id, name, definitionNames) {\n  this.id = id;\n  this.name = name;\n  this.startTime = new Date().getTime();\n  this.steps = [];\n  this.fullDefinitionName = (definitionNames || []).join(' ');\n};\n\n/**\n * Adds a new step to the Spec.\n *\n * @param {string} step Name of the step (really name of the future)\n * @return {Object} the added step\n */\nangular.scenario.ObjectModel.Spec.prototype.addStep = function(name) {\n  var step = new angular.scenario.ObjectModel.Step(name);\n  this.steps.push(step);\n  return step;\n};\n\n/**\n * Gets the most recent step.\n *\n * @return {Object} the step\n */\nangular.scenario.ObjectModel.Spec.prototype.getLastStep = function() {\n  return this.steps[this.steps.length-1];\n};\n\n/**\n * Set status of the Spec from given Step\n *\n * @param {angular.scenario.ObjectModel.Step} step\n */\nangular.scenario.ObjectModel.Spec.prototype.setStatusFromStep = function(step) {\n  if (!this.status || step.status == 'error') {\n    this.status = step.status;\n    this.error = step.error;\n    this.line = step.line;\n  }\n};\n\n/**\n * A single step inside a Spec.\n *\n * @param {string} step Name of the step\n */\nangular.scenario.ObjectModel.Step = function(name) {\n  this.name = name;\n  this.startTime = new Date().getTime();\n};\n\n/**\n * Helper method for setting all error status related properties\n *\n * @param {string} status\n * @param {string} error\n * @param {string} line\n */\nangular.scenario.ObjectModel.Step.prototype.setErrorStatus = function(status, error, line) {\n  this.status = status;\n  this.error = error;\n  this.line = line;\n};\n\n/**\n * Runner for scenarios\n *\n * Has to be initialized before any test is loaded,\n * because it publishes the API into window (global space).\n */\nangular.scenario.Runner = function($window) {\n  this.listeners = [];\n  this.$window = $window;\n  this.rootDescribe = new angular.scenario.Describe();\n  this.currentDescribe = this.rootDescribe;\n  this.api = {\n    it: this.it,\n    iit: this.iit,\n    xit: angular.noop,\n    describe: this.describe,\n    ddescribe: this.ddescribe,\n    xdescribe: angular.noop,\n    beforeEach: this.beforeEach,\n    afterEach: this.afterEach\n  };\n  angular.forEach(this.api, angular.bind(this, function(fn, key) {\n    this.$window[key] = angular.bind(this, fn);\n  }));\n};\n\n/**\n * Emits an event which notifies listeners and passes extra\n * arguments.\n *\n * @param {string} eventName Name of the event to fire.\n */\nangular.scenario.Runner.prototype.emit = function(eventName) {\n  var self = this;\n  var args = Array.prototype.slice.call(arguments, 1);\n  eventName = eventName.toLowerCase();\n  if (!this.listeners[eventName])\n    return;\n  angular.forEach(this.listeners[eventName], function(listener) {\n    listener.apply(self, args);\n  });\n};\n\n/**\n * Adds a listener for an event.\n *\n * @param {string} eventName The name of the event to add a handler for\n * @param {string} listener The fn(...) that takes the extra arguments from emit()\n */\nangular.scenario.Runner.prototype.on = function(eventName, listener) {\n  eventName = eventName.toLowerCase();\n  this.listeners[eventName] = this.listeners[eventName] || [];\n  this.listeners[eventName].push(listener);\n};\n\n/**\n * Defines a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.describe = function(name, body) {\n  var self = this;\n  this.currentDescribe.describe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Same as describe, but makes ddescribe the only blocks to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.ddescribe = function(name, body) {\n  var self = this;\n  this.currentDescribe.ddescribe(name, function() {\n    var parentDescribe = self.currentDescribe;\n    self.currentDescribe = this;\n    try {\n      body.call(this);\n    } finally {\n      self.currentDescribe = parentDescribe;\n    }\n  });\n};\n\n/**\n * Defines a test in a describe block of a spec.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.it = function(name, body) {\n  this.currentDescribe.it(name, body);\n};\n\n/**\n * Same as it, but makes iit tests the only tests to run.\n *\n * @see Describe.js\n *\n * @param {string} name Name of the block\n * @param {function()} body Body of the block\n */\nangular.scenario.Runner.prototype.iit = function(name, body) {\n  this.currentDescribe.iit(name, body);\n};\n\n/**\n * Defines a function to be called before each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.beforeEach = function(body) {\n  this.currentDescribe.beforeEach(body);\n};\n\n/**\n * Defines a function to be called after each it block in the describe\n * (and before all nested describes).\n *\n * @see Describe.js\n *\n * @param {function()} Callback to execute\n */\nangular.scenario.Runner.prototype.afterEach = function(body) {\n  this.currentDescribe.afterEach(body);\n};\n\n/**\n * Creates a new spec runner.\n *\n * @private\n * @param {Object} scope parent scope\n */\nangular.scenario.Runner.prototype.createSpecRunner_ = function(scope) {\n  var child = scope.$new();\n  var Cls = angular.scenario.SpecRunner;\n\n  // Export all the methods to child scope manually as now we don't mess controllers with scopes\n  // TODO(vojta): refactor scenario runner so that these objects are not tightly coupled as current\n  for (var name in Cls.prototype)\n    child[name] = angular.bind(child, Cls.prototype[name]);\n\n  Cls.call(child);\n  return child;\n};\n\n/**\n * Runs all the loaded tests with the specified runner class on the\n * provided application.\n *\n * @param {angular.scenario.Application} application App to remote control.\n */\nangular.scenario.Runner.prototype.run = function(application) {\n  var self = this;\n  var $root = angular.injector(['ng']).get('$rootScope');\n  angular.extend($root, this);\n  angular.forEach(angular.scenario.Runner.prototype, function(fn, name) {\n    $root[name] = angular.bind(self, fn);\n  });\n  $root.application = application;\n  $root.emit('RunnerBegin');\n  asyncForEach(this.rootDescribe.getSpecs(), function(spec, specDone) {\n    var dslCache = {};\n    var runner = self.createSpecRunner_($root);\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      dslCache[key] = fn.call($root);\n    });\n    angular.forEach(angular.scenario.dsl, function(fn, key) {\n      self.$window[key] = function() {\n        var line = callerFile(3);\n        var scope = runner.$new();\n\n        // Make the dsl accessible on the current chain\n        scope.dsl = {};\n        angular.forEach(dslCache, function(fn, key) {\n          scope.dsl[key] = function() {\n            return dslCache[key].apply(scope, arguments);\n          };\n        });\n\n        // Make these methods work on the current chain\n        scope.addFuture = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFuture.apply(scope, arguments);\n        };\n        scope.addFutureAction = function() {\n          Array.prototype.push.call(arguments, line);\n          return angular.scenario.SpecRunner.\n            prototype.addFutureAction.apply(scope, arguments);\n        };\n\n        return scope.dsl[key].apply(scope, arguments);\n      };\n    });\n    runner.run(spec, function() {\n      runner.$destroy();\n      specDone.apply(this, arguments);\n    });\n  },\n  function(error) {\n    if (error) {\n      self.emit('RunnerError', error);\n    }\n    self.emit('RunnerEnd');\n  });\n};\n\n/**\n * This class is the \"this\" of the it/beforeEach/afterEach method.\n * Responsibilities:\n *   - \"this\" for it/beforeEach/afterEach\n *   - keep state for single it/beforeEach/afterEach execution\n *   - keep track of all of the futures to execute\n *   - run single spec (execute each future)\n */\nangular.scenario.SpecRunner = function() {\n  this.futures = [];\n  this.afterIndex = 0;\n};\n\n/**\n * Executes a spec which is an it block with associated before/after functions\n * based on the describe nesting.\n *\n * @param {Object} spec A spec object\n * @param {function()} specDone function that is called when the spec finshes. Function(error, index)\n */\nangular.scenario.SpecRunner.prototype.run = function(spec, specDone) {\n  var self = this;\n  this.spec = spec;\n\n  this.emit('SpecBegin', spec);\n\n  try {\n    spec.before.call(this);\n    spec.body.call(this);\n    this.afterIndex = this.futures.length;\n    spec.after.call(this);\n  } catch (e) {\n    this.emit('SpecError', spec, e);\n    this.emit('SpecEnd', spec);\n    specDone();\n    return;\n  }\n\n  var handleError = function(error, done) {\n    if (self.error) {\n      return done();\n    }\n    self.error = true;\n    done(null, self.afterIndex);\n  };\n\n  asyncForEach(\n    this.futures,\n    function(future, futureDone) {\n      self.step = future;\n      self.emit('StepBegin', spec, future);\n      try {\n        future.execute(function(error) {\n          if (error) {\n            self.emit('StepFailure', spec, future, error);\n            self.emit('StepEnd', spec, future);\n            return handleError(error, futureDone);\n          }\n          self.emit('StepEnd', spec, future);\n          self.$window.setTimeout(function() { futureDone(); }, 0);\n        });\n      } catch (e) {\n        self.emit('StepError', spec, future, e);\n        self.emit('StepEnd', spec, future);\n        handleError(e, futureDone);\n      }\n    },\n    function(e) {\n      if (e) {\n        self.emit('SpecError', spec, e);\n      }\n      self.emit('SpecEnd', spec);\n      // Call done in a timeout so exceptions don't recursively\n      // call this function\n      self.$window.setTimeout(function() { specDone(); }, 0);\n    }\n  );\n};\n\n/**\n * Adds a new future action.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFuture = function(name, behavior, line) {\n  var future = new angular.scenario.Future(name, angular.bind(this, behavior), line);\n  this.futures.push(future);\n  return future;\n};\n\n/**\n * Adds a new future action to be executed on the application window.\n *\n * Note: Do not pass line manually. It happens automatically.\n *\n * @param {string} name Name of the future\n * @param {function()} behavior Behavior of the future\n * @param {function()} line fn() that returns file/line number\n */\nangular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior, line) {\n  var self = this;\n  var NG = /\\[ng\\\\\\:/;\n  return this.addFuture(name, function(done) {\n    this.application.executeAction(function($window, $document) {\n\n      //TODO(esprehn): Refactor this so it doesn't need to be in here.\n      $document.elements = function(selector) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        selector = (self.selector || '') + ' ' + (selector || '');\n        selector = _jQuery.trim(selector) || '*';\n        angular.forEach(args, function(value, index) {\n          selector = selector.replace('$' + (index + 1), value);\n        });\n        var result = $document.find(selector);\n        if (selector.match(NG)) {\n          angular.forEach(['[ng-','[data-ng-','[x-ng-'], function(value, index){\n            result = result.add(selector.replace(NG, value), $document);\n          });\n        }\n        if (!result.length) {\n          throw {\n            type: 'selector',\n            message: 'Selector ' + selector + ' did not match any elements.'\n          };\n        }\n\n        return result;\n      };\n\n      try {\n        behavior.call(self, $window, $document, done);\n      } catch(e) {\n        if (e.type && e.type === 'selector') {\n          done(e.message);\n        } else {\n          throw e;\n        }\n      }\n    });\n  }, line);\n};\n\n/**\n * Shared DSL statements that are useful to all scenarios.\n */\n\n /**\n * Usage:\n *    pause() pauses until you call resume() in the console\n */\nangular.scenario.dsl('pause', function() {\n  return function() {\n    return this.addFuture('pausing for you to resume', function(done) {\n      this.emit('InteractivePause', this.spec, this.step);\n      this.$window.resume = function() { done(); };\n    });\n  };\n});\n\n/**\n * Usage:\n *    sleep(seconds) pauses the test for specified number of seconds\n */\nangular.scenario.dsl('sleep', function() {\n  return function(time) {\n    return this.addFuture('sleep for ' + time + ' seconds', function(done) {\n      this.$window.setTimeout(function() { done(null, time * 1000); }, time * 1000);\n    });\n  };\n});\n\n/**\n * Usage:\n *    browser().navigateTo(url) Loads the url into the frame\n *    browser().navigateTo(url, fn) where fn(url) is called and returns the URL to navigate to\n *    browser().reload() refresh the page (reload the same URL)\n *    browser().window.href() window.location.href\n *    browser().window.path() window.location.pathname\n *    browser().window.search() window.location.search\n *    browser().window.hash() window.location.hash without # prefix\n *    browser().location().url() see ng.$location#url\n *    browser().location().path() see ng.$location#path\n *    browser().location().search() see ng.$location#search\n *    browser().location().hash() see ng.$location#hash\n */\nangular.scenario.dsl('browser', function() {\n  var chain = {};\n\n  chain.navigateTo = function(url, delegate) {\n    var application = this.application;\n    return this.addFuture(\"browser navigate to '\" + url + \"'\", function(done) {\n      if (delegate) {\n        url = delegate.call(this, url);\n      }\n      application.navigateTo(url, function() {\n        done(null, url);\n      }, done);\n    });\n  };\n\n  chain.reload = function() {\n    var application = this.application;\n    return this.addFutureAction('browser reload', function($window, $document, done) {\n      var href = $window.location.href;\n      application.navigateTo(href, function() {\n        done(null, href);\n      }, done);\n    });\n  };\n\n  chain.window = function() {\n    var api = {};\n\n    api.href = function() {\n      return this.addFutureAction('window.location.href', function($window, $document, done) {\n        done(null, $window.location.href);\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('window.location.path', function($window, $document, done) {\n        done(null, $window.location.pathname);\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('window.location.search', function($window, $document, done) {\n        done(null, $window.location.search);\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('window.location.hash', function($window, $document, done) {\n        done(null, $window.location.hash.replace('#', ''));\n      });\n    };\n\n    return api;\n  };\n\n  chain.location = function() {\n    var api = {};\n\n    api.url = function() {\n      return this.addFutureAction('$location.url()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').url());\n      });\n    };\n\n    api.path = function() {\n      return this.addFutureAction('$location.path()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').path());\n      });\n    };\n\n    api.search = function() {\n      return this.addFutureAction('$location.search()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').search());\n      });\n    };\n\n    api.hash = function() {\n      return this.addFutureAction('$location.hash()', function($window, $document, done) {\n        done(null, $document.injector().get('$location').hash());\n      });\n    };\n\n    return api;\n  };\n\n  return function() {\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    expect(future).{matcher} where matcher is one of the matchers defined\n *    with angular.scenario.matcher\n *\n * ex. expect(binding(\"name\")).toEqual(\"Elliott\")\n */\nangular.scenario.dsl('expect', function() {\n  var chain = angular.extend({}, angular.scenario.matcher);\n\n  chain.not = function() {\n    this.inverse = true;\n    return chain;\n  };\n\n  return function(future) {\n    this.future = future;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    using(selector, label) scopes the next DSL element selection\n *\n * ex.\n *   using('#foo', \"'Foo' text field\").input('bar')\n */\nangular.scenario.dsl('using', function() {\n  return function(selector, label) {\n    this.selector = _jQuery.trim((this.selector||'') + ' ' + selector);\n    if (angular.isString(label) && label.length) {\n      this.label = label + ' ( ' + this.selector + ' )';\n    } else {\n      this.label = this.selector;\n    }\n    return this.dsl;\n  };\n});\n\n/**\n * Usage:\n *    binding(name) returns the value of the first matching binding\n */\nangular.scenario.dsl('binding', function() {\n  return function(name) {\n    return this.addFutureAction(\"select binding '\" + name + \"'\", function($window, $document, done) {\n      var values = $document.elements().bindings($window.angular.element, name);\n      if (!values.length) {\n        return done(\"Binding selector '\" + name + \"' did not match.\");\n      }\n      done(null, values[0]);\n    });\n  };\n});\n\n/**\n * Usage:\n *    input(name).enter(value) enters value in input with specified name\n *    input(name).check() checks checkbox\n *    input(name).select(value) selects the radio button with specified name/value\n *    input(name).val() returns the value of the input.\n */\nangular.scenario.dsl('input', function() {\n  var chain = {};\n  var supportInputEvent =  'oninput' in document.createElement('div') && msie != 9;\n\n  chain.enter = function(value, event) {\n    return this.addFutureAction(\"input '\" + this.name + \"' enter '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      input.val(value);\n      input.trigger(event || (supportInputEvent ? 'input' : 'change'));\n      done();\n    });\n  };\n\n  chain.check = function() {\n    return this.addFutureAction(\"checkbox '\" + this.name + \"' toggle\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':checkbox');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.select = function(value) {\n    return this.addFutureAction(\"radio button '\" + this.name + \"' toggle '\" + value + \"'\", function($window, $document, done) {\n      var input = $document.\n        elements('[ng\\\\:model=\"$1\"][value=\"$2\"]', this.name, value).filter(':radio');\n      input.trigger('click');\n      done();\n    });\n  };\n\n  chain.val = function() {\n    return this.addFutureAction(\"return input val\", function($window, $document, done) {\n      var input = $document.elements('[ng\\\\:model=\"$1\"]', this.name).filter(':input');\n      done(null,input.val());\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n\n/**\n * Usage:\n *    repeater('#products table', 'Product List').count() number of rows\n *    repeater('#products table', 'Product List').row(1) all bindings in row as an array\n *    repeater('#products table', 'Product List').column('product.name') all values across all rows in an array\n */\nangular.scenario.dsl('repeater', function() {\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.column = function(binding) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' column '\" + binding + \"'\", function($window, $document, done) {\n      done(null, $document.elements().bindings($window.angular.element, binding));\n    });\n  };\n\n  chain.row = function(index) {\n    return this.addFutureAction(\"repeater '\" + this.label + \"' row '\" + index + \"'\", function($window, $document, done) {\n      var matches = $document.elements().slice(index, index + 1);\n      if (!matches.length)\n        return done('row ' + index + ' out of bounds');\n      done(null, matches.bindings($window.angular.element));\n    });\n  };\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    select(name).option('value') select one option\n *    select(name).options('value1', 'value2', ...) select options from a multi select\n */\nangular.scenario.dsl('select', function() {\n  var chain = {};\n\n  chain.option = function(value) {\n    return this.addFutureAction(\"select '\" + this.name + \"' option '\" + value + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[ng\\\\:model=\"$1\"]', this.name);\n      var option = select.find('option[value=\"' + value + '\"]');\n      if (option.length) {\n        select.val(value);\n      } else {\n        option = select.find('option:contains(\"' + value + '\")');\n        if (option.length) {\n          select.val(option.val());\n        }\n      }\n      select.trigger('change');\n      done();\n    });\n  };\n\n  chain.options = function() {\n    var values = arguments;\n    return this.addFutureAction(\"select '\" + this.name + \"' options '\" + values + \"'\", function($window, $document, done) {\n      var select = $document.elements('select[multiple][ng\\\\:model=\"$1\"]', this.name);\n      select.val(values);\n      select.trigger('change');\n      done();\n    });\n  };\n\n  return function(name) {\n    this.name = name;\n    return chain;\n  };\n});\n\n/**\n * Usage:\n *    element(selector, label).count() get the number of elements that match selector\n *    element(selector, label).click() clicks an element\n *    element(selector, label).query(fn) executes fn(selectedElements, done)\n *    element(selector, label).{method}() gets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(value) sets the value (as defined by jQuery, ex. val)\n *    element(selector, label).{method}(key) gets the value (as defined by jQuery, ex. attr)\n *    element(selector, label).{method}(key, value) sets the value (as defined by jQuery, ex. attr)\n */\nangular.scenario.dsl('element', function() {\n  var KEY_VALUE_METHODS = ['attr', 'css', 'prop'];\n  var VALUE_METHODS = [\n    'val', 'text', 'html', 'height', 'innerHeight', 'outerHeight', 'width',\n    'innerWidth', 'outerWidth', 'position', 'scrollLeft', 'scrollTop', 'offset'\n  ];\n  var chain = {};\n\n  chain.count = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' count\", function($window, $document, done) {\n      try {\n        done(null, $document.elements().length);\n      } catch (e) {\n        done(null, 0);\n      }\n    });\n  };\n\n  chain.click = function() {\n    return this.addFutureAction(\"element '\" + this.label + \"' click\", function($window, $document, done) {\n      var elements = $document.elements();\n      var href = elements.attr('href');\n      var eventProcessDefault = elements.trigger('click')[0];\n\n      if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {\n        this.application.navigateTo(href, function() {\n          done();\n        }, done);\n      } else {\n        done();\n      }\n    });\n  };\n\n  chain.query = function(fn) {\n    return this.addFutureAction('element ' + this.label + ' custom query', function($window, $document, done) {\n      fn.call(this, $document.elements(), done);\n    });\n  };\n\n  angular.forEach(KEY_VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(name, value) {\n      var args = arguments,\n          futureName = (args.length == 1)\n              ? \"element '\" + this.label + \"' get \" + methodName + \" '\" + name + \"'\"\n              : \"element '\" + this.label + \"' set \" + methodName + \" '\" + name + \"' to \" + \"'\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  angular.forEach(VALUE_METHODS, function(methodName) {\n    chain[methodName] = function(value) {\n      var args = arguments,\n          futureName = (args.length == 0)\n              ? \"element '\" + this.label + \"' \" + methodName\n              : futureName = \"element '\" + this.label + \"' set \" + methodName + \" to '\" + value + \"'\";\n\n      return this.addFutureAction(futureName, function($window, $document, done) {\n        var element = $document.elements();\n        done(null, element[methodName].apply(element, args));\n      });\n    };\n  });\n\n  return function(selector, label) {\n    this.dsl.using(selector, label);\n    return chain;\n  };\n});\n\n/**\n * Matchers for implementing specs. Follows the Jasmine spec conventions.\n */\n\nangular.scenario.matcher('toEqual', function(expected) {\n  return angular.equals(this.actual, expected);\n});\n\nangular.scenario.matcher('toBe', function(expected) {\n  return this.actual === expected;\n});\n\nangular.scenario.matcher('toBeDefined', function() {\n  return angular.isDefined(this.actual);\n});\n\nangular.scenario.matcher('toBeTruthy', function() {\n  return this.actual;\n});\n\nangular.scenario.matcher('toBeFalsy', function() {\n  return !this.actual;\n});\n\nangular.scenario.matcher('toMatch', function(expected) {\n  return new RegExp(expected).test(this.actual);\n});\n\nangular.scenario.matcher('toBeNull', function() {\n  return this.actual === null;\n});\n\nangular.scenario.matcher('toContain', function(expected) {\n  return includes(this.actual, expected);\n});\n\nangular.scenario.matcher('toBeLessThan', function(expected) {\n  return this.actual < expected;\n});\n\nangular.scenario.matcher('toBeGreaterThan', function(expected) {\n  return this.actual > expected;\n});\n\n/**\n * User Interface for the Scenario Runner.\n *\n * TODO(esprehn): This should be refactored now that ObjectModel exists\n *  to use angular bindings for the UI.\n */\nangular.scenario.output('html', function(context, runner, model) {\n  var specUiMap = {},\n      lastStepUiMap = {};\n\n  context.append(\n    '<div id=\"header\">' +\n    '  <h1><span class=\"angular\">AngularJS</span>: Scenario Test Runner</h1>' +\n    '  <ul id=\"status-legend\" class=\"status-display\">' +\n    '    <li class=\"status-error\">0 Errors</li>' +\n    '    <li class=\"status-failure\">0 Failures</li>' +\n    '    <li class=\"status-success\">0 Passed</li>' +\n    '  </ul>' +\n    '</div>' +\n    '<div id=\"specs\">' +\n    '  <div class=\"test-children\"></div>' +\n    '</div>'\n  );\n\n  runner.on('InteractivePause', function(spec) {\n    var ui = lastStepUiMap[spec.id];\n    ui.find('.test-title').\n      html('paused... <a href=\"javascript:resume()\">resume</a> when ready.');\n  });\n\n  runner.on('SpecBegin', function(spec) {\n    var ui = findContext(spec);\n    ui.find('> .tests').append(\n      '<li class=\"status-pending test-it\"></li>'\n    );\n    ui = ui.find('> .tests li:last');\n    ui.append(\n      '<div class=\"test-info\">' +\n      '  <p class=\"test-title\">' +\n      '    <span class=\"timer-result\"></span>' +\n      '    <span class=\"test-name\"></span>' +\n      '  </p>' +\n      '</div>' +\n      '<div class=\"scrollpane\">' +\n      '  <ol class=\"test-actions\"></ol>' +\n      '</div>'\n    );\n    ui.find('> .test-info .test-name').text(spec.name);\n    ui.find('> .test-info').click(function() {\n      var scrollpane = ui.find('> .scrollpane');\n      var actions = scrollpane.find('> .test-actions');\n      var name = context.find('> .test-info .test-name');\n      if (actions.find(':visible').length) {\n        actions.hide();\n        name.removeClass('open').addClass('closed');\n      } else {\n        actions.show();\n        scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n        name.removeClass('closed').addClass('open');\n      }\n    });\n\n    specUiMap[spec.id] = ui;\n  });\n\n  runner.on('SpecError', function(spec, error) {\n    var ui = specUiMap[spec.id];\n    ui.append('<pre></pre>');\n    ui.find('> pre').text(formatException(error));\n  });\n\n  runner.on('SpecEnd', function(spec) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    ui.removeClass('status-pending');\n    ui.addClass('status-' + spec.status);\n    ui.find(\"> .test-info .timer-result\").text(spec.duration + \"ms\");\n    if (spec.status === 'success') {\n      ui.find('> .test-info .test-name').addClass('closed');\n      ui.find('> .scrollpane .test-actions').hide();\n    }\n    updateTotals(spec.status);\n  });\n\n  runner.on('StepBegin', function(spec, step) {\n    var ui = specUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    ui.find('> .scrollpane .test-actions').append('<li class=\"status-pending\"></li>');\n    var stepUi = lastStepUiMap[spec.id] = ui.find('> .scrollpane .test-actions li:last');\n    stepUi.append(\n      '<div class=\"timer-result\"></div>' +\n      '<div class=\"test-title\"></div>'\n    );\n    stepUi.find('> .test-title').text(step.name);\n    var scrollpane = stepUi.parents('.scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  runner.on('StepFailure', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepError', function(spec, step, error) {\n    var ui = lastStepUiMap[spec.id];\n    addError(ui, step.line, error);\n  });\n\n  runner.on('StepEnd', function(spec, step) {\n    var stepUi = lastStepUiMap[spec.id];\n    spec = model.getSpec(spec.id);\n    step = spec.getLastStep();\n    stepUi.find('.timer-result').text(step.duration + 'ms');\n    stepUi.removeClass('status-pending');\n    stepUi.addClass('status-' + step.status);\n    var scrollpane = specUiMap[spec.id].find('> .scrollpane');\n    scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));\n  });\n\n  /**\n   * Finds the context of a spec block defined by the passed definition.\n   *\n   * @param {Object} The definition created by the Describe object.\n   */\n  function findContext(spec) {\n    var currentContext = context.find('#specs');\n    angular.forEach(model.getDefinitionPath(spec), function(defn) {\n      var id = 'describe-' + defn.id;\n      if (!context.find('#' + id).length) {\n        currentContext.find('> .test-children').append(\n          '<div class=\"test-describe\" id=\"' + id + '\">' +\n          '  <h2></h2>' +\n          '  <div class=\"test-children\"></div>' +\n          '  <ul class=\"tests\"></ul>' +\n          '</div>'\n        );\n        context.find('#' + id).find('> h2').text('describe: ' + defn.name);\n      }\n      currentContext = context.find('#' + id);\n    });\n    return context.find('#describe-' + spec.definition.id);\n  }\n\n  /**\n   * Updates the test counter for the status.\n   *\n   * @param {string} the status.\n   */\n  function updateTotals(status) {\n    var legend = context.find('#status-legend .status-' + status);\n    var parts = legend.text().split(' ');\n    var value = (parts[0] * 1) + 1;\n    legend.text(value + ' ' + parts[1]);\n  }\n\n  /**\n   * Add an error to a step.\n   *\n   * @param {Object} The JQuery wrapped context\n   * @param {function()} fn() that should return the file/line number of the error\n   * @param {Object} the error.\n   */\n  function addError(context, line, error) {\n    context.find('.test-title').append('<pre></pre>');\n    var message = _jQuery.trim(line() + '\\n\\n' + formatException(error));\n    context.find('.test-title pre:last').text(message);\n  }\n});\n\n/**\n * Generates JSON output into a context.\n */\nangular.scenario.output('json', function(context, runner, model) {\n  model.on('RunnerEnd', function() {\n    context.text(angular.toJson(model.value));\n  });\n});\n\n/**\n * Generates XML output into a context.\n */\nangular.scenario.output('xml', function(context, runner, model) {\n  var $ = function(args) {return new context.init(args);};\n  model.on('RunnerEnd', function() {\n    var scenario = $('<scenario></scenario>');\n    context.append(scenario);\n    serializeXml(scenario, model.value);\n  });\n\n  /**\n   * Convert the tree into XML.\n   *\n   * @param {Object} context jQuery context to add the XML to.\n   * @param {Object} tree node to serialize\n   */\n  function serializeXml(context, tree) {\n     angular.forEach(tree.children, function(child) {\n       var describeContext = $('<describe></describe>');\n       describeContext.attr('id', child.id);\n       describeContext.attr('name', child.name);\n       context.append(describeContext);\n       serializeXml(describeContext, child);\n     });\n     var its = $('<its></its>');\n     context.append(its);\n     angular.forEach(tree.specs, function(spec) {\n       var it = $('<it></it>');\n       it.attr('id', spec.id);\n       it.attr('name', spec.name);\n       it.attr('duration', spec.duration);\n       it.attr('status', spec.status);\n       its.append(it);\n       angular.forEach(spec.steps, function(step) {\n         var stepContext = $('<step></step>');\n         stepContext.attr('name', step.name);\n         stepContext.attr('duration', step.duration);\n         stepContext.attr('status', step.status);\n         it.append(stepContext);\n         if (step.error) {\n           var error = $('<error></error>');\n           stepContext.append(error);\n           error.text(formatException(stepContext.error));\n         }\n       });\n     });\n   }\n});\n\n/**\n * Creates a global value $result with the result of the runner.\n */\nangular.scenario.output('object', function(context, runner, model) {\n  runner.$window.$result = model.value;\n});\nbindJQuery();\npublishExternalAPI(angular);\n\nvar $runner = new angular.scenario.Runner(window),\n    scripts = document.getElementsByTagName('script'),\n    script = scripts[scripts.length - 1],\n    config = {};\n\nangular.forEach(script.attributes, function(attr) {\n  var match = attr.name.match(/ng[:\\-](.*)/);\n  if (match) {\n    config[match[1]] = attr.value || true;\n  }\n});\n\nif (config.autotest) {\n  JQLite(document).ready(function() {\n    angular.scenario.setUpAndRun(config);\n  });\n}\n})(window, document);\n\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n\\n[ng\\\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\\n.ng-cloak, .x-ng-cloak {\\n  display: none;\\n}\\n\\nng\\\\:form {\\n  display: block;\\n}\\n</style>');\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";\\n/* CSS Document */\\n\\n/** Structure */\\nbody {\\n  font-family: Arial, sans-serif;\\n  margin: 0;\\n  font-size: 14px;\\n}\\n\\n#system-error {\\n  font-size: 1.5em;\\n  text-align: center;\\n}\\n\\n#json, #xml {\\n  display: none;\\n}\\n\\n#header {\\n  position: fixed;\\n  width: 100%;\\n}\\n\\n#specs {\\n  padding-top: 50px;\\n}\\n\\n#header .angular {\\n  font-family: Courier New, monospace;\\n  font-weight: bold;\\n}\\n\\n#header h1 {\\n  font-weight: normal;\\n  float: left;\\n  font-size: 30px;\\n  line-height: 30px;\\n  margin: 0;\\n  padding: 10px 10px;\\n  height: 30px;\\n}\\n\\n#application h2,\\n#specs h2 {\\n  margin: 0;\\n  padding: 0.5em;\\n  font-size: 1.1em;\\n}\\n\\n#status-legend {\\n  margin-top: 10px;\\n  margin-right: 10px;\\n}\\n\\n#header,\\n#application,\\n.test-info,\\n.test-actions li {\\n  overflow: hidden;\\n}\\n\\n#application {\\n  margin: 10px;\\n}\\n\\n#application iframe {\\n  width: 100%;\\n  height: 758px;\\n}\\n\\n#application .popout {\\n  float: right;\\n}\\n\\n#application iframe {\\n  border: none;\\n}\\n\\n.tests li,\\n.test-actions li,\\n.test-it li,\\n.test-it ol,\\n.status-display {\\n  list-style-type: none;\\n}\\n\\n.tests,\\n.test-it ol,\\n.status-display {\\n  margin: 0;\\n  padding: 0;\\n}\\n\\n.test-info {\\n  margin-left: 1em;\\n  margin-top: 0.5em;\\n  border-radius: 8px 0 0 8px;\\n  -webkit-border-radius: 8px 0 0 8px;\\n  -moz-border-radius: 8px 0 0 8px;\\n  cursor: pointer;\\n}\\n\\n.test-info:hover .test-name {\\n  text-decoration: underline;\\n}\\n\\n.test-info .closed:before {\\n  content: \\'\\\\25b8\\\\00A0\\';\\n}\\n\\n.test-info .open:before {\\n  content: \\'\\\\25be\\\\00A0\\';\\n  font-weight: bold;\\n}\\n\\n.test-it ol {\\n  margin-left: 2.5em;\\n}\\n\\n.status-display,\\n.status-display li {\\n  float: right;\\n}\\n\\n.status-display li {\\n  padding: 5px 10px;\\n}\\n\\n.timer-result,\\n.test-title {\\n  display: inline-block;\\n  margin: 0;\\n  padding: 4px;\\n}\\n\\n.test-actions .test-title,\\n.test-actions .test-result {\\n  display: table-cell;\\n  padding-left: 0.5em;\\n  padding-right: 0.5em;\\n}\\n\\n.test-actions {\\n  display: table;\\n}\\n\\n.test-actions li {\\n  display: table-row;\\n}\\n\\n.timer-result {\\n  width: 4em;\\n  padding: 0 10px;\\n  text-align: right;\\n  font-family: monospace;\\n}\\n\\n.test-it pre,\\n.test-actions pre {\\n  clear: left;\\n  color: black;\\n  margin-left: 6em;\\n}\\n\\n.test-describe {\\n  padding-bottom: 0.5em;\\n}\\n\\n.test-describe .test-describe {\\n  margin: 5px 5px 10px 2em;\\n}\\n\\n.test-actions .status-pending .test-title:before {\\n  content: \\'\\\\00bb\\\\00A0\\';\\n}\\n\\n.scrollpane {\\n   max-height: 20em;\\n   overflow: auto;\\n}\\n\\n/** Colors */\\n\\n#header {\\n  background-color: #F2C200;\\n}\\n\\n#specs h2 {\\n  border-top: 2px solid #BABAD1;\\n}\\n\\n#specs h2,\\n#application h2 {\\n  background-color: #efefef;\\n}\\n\\n#application {\\n  border: 1px solid #BABAD1;\\n}\\n\\n.test-describe .test-describe {\\n  border-left: 1px solid #BABAD1;\\n  border-right: 1px solid #BABAD1;\\n  border-bottom: 1px solid #BABAD1;\\n}\\n\\n.status-display {\\n  border: 1px solid #777;\\n}\\n\\n.status-display .status-pending,\\n.status-pending .test-info {\\n  background-color: #F9EEBC;\\n}\\n\\n.status-display .status-success,\\n.status-success .test-info {\\n  background-color: #B1D7A1;\\n}\\n\\n.status-display .status-failure,\\n.status-failure .test-info {\\n  background-color: #FF8286;\\n}\\n\\n.status-display .status-error,\\n.status-error .test-info {\\n  background-color: black;\\n  color: white;\\n}\\n\\n.test-actions .status-success .test-title {\\n  color: #30B30A;\\n}\\n\\n.test-actions .status-failure .test-title {\\n  color: #DF0000;\\n}\\n\\n.test-actions .status-error .test-title {\\n  color: black;\\n}\\n\\n.test-actions .timer-result {\\n  color: #888;\\n}\\n</style>');"
  },
  {
    "path": "chapter6/recipe4/test/lib/angular/version.txt",
    "content": "1.0.4\n"
  },
  {
    "path": "chapter7/recipe1/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter7/recipe1/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <div ng-controller=\"User\">\n      <form ng-submit=\"submit()\" novalidate>\n        <label>Firstname</label>\n        <input type=\"text\" ng-model=\"user.firstname\"/>\n        <label>Lastname</label>\n        <input type=\"text\" ng-model=\"user.lastname\"/>\n        <label>Age</label>\n        <input type=\"text\" ng-model=\"user.age\"/>\n        <br>\n        <button class=\"btn\">Submit</button>\n      </form>\n\n      User Model: {{user}}\n      <br>\n      Form was submitted: {{wasSubmitted}}\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter7/recipe1/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter7/recipe1/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.controller(\"User\", function($scope) {\n  $scope.user = {};\n  $scope.wasSubmitted = false;\n\n  $scope.submit = function() {\n    $scope.wasSubmitted = true;\n  };\n});"
  },
  {
    "path": "chapter7/recipe2/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter7/recipe2/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <div ng-controller=\"User\">\n      <form name=\"form\" ng-submit=\"submit()\" novalidate>\n        <label>Firstname</label>\n        <input name=\"firstname\" type=\"text\" ng-model=\"user.firstname\" required/>\n        <label>Lastname</label>\n        <input type=\"text\" ng-model=\"user.lastname\" required/>\n        <label>Age</label>\n        <input type=\"text\" ng-model=\"user.age\"/>\n        <br>\n        <button class=\"btn\">Submit</button>\n      </form>\n\n      User Model: {{user}}\n      <br>\n      Form was submitted: {{wasSubmitted}}\n      <br>\n      Firstname input valid: {{form.firstname.$valid}}\n      <br>\n      Firstname input invalid: {{form.firstname.$invalid}}\n      <br>\n      Firstname validation error: {{form.firstname.$error}}\n      <br>\n      Form valid: {{form.$valid}}\n      <br>\n      Form validation error: {{form.$error}}\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter7/recipe2/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter7/recipe2/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.controller(\"User\", function($scope) {\n  $scope.user = {};\n  $scope.wasSubmitted = false;\n\n  $scope.submit = function() {\n    $scope.wasSubmitted = true;\n  };\n});"
  },
  {
    "path": "chapter7/recipe3/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter7/recipe3/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n    <style type=\"text/css\">\n      input.ng-invalid.ng-dirty {\n        background-color: red;\n      }\n      input.ng-valid.ng-dirty {\n        background-color: green;\n      }\n    </style>\n  </head>\n  <body ng-app=\"MyApp\">\n    <div ng-controller=\"User\">\n      <form name=\"form\" ng-submit=\"submit()\" class=\"form-horizontal\" novalidate>\n        <label>Firstname</label>\n        <input name=\"firstname\" type=\"text\" ng-model=\"user.firstname\" required/>\n        <p ng-show=\"form.firstname.$invalid && form.firstname.$dirty\">Firstname is required</p>\n        <label>Lastname</label>\n        <input type=\"text\" ng-model=\"user.lastname\" required/>\n        <label>Age</label>\n        <input type=\"text\" ng-model=\"user.age\"/>\n        <br>\n        <button class=\"btn\">Submit</button>\n      </form>\n\n      User Model: {{user}}\n      <br>\n      Form was submitted: {{wasSubmitted}}\n      <br>\n      Firstname input valid: {{form.firstname.$valid}}\n      <br>\n      Firstname validation error: {{form.firstname.$error}}\n      <br>\n      Form valid: {{form.$valid}}\n      <br>\n      Form validation error: {{form.$error}}\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter7/recipe3/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter7/recipe3/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.controller(\"User\", function($scope) {\n  $scope.user = {};\n  $scope.wasSubmitted = false;\n\n  $scope.submit = function() {\n    $scope.wasSubmitted = true;\n  };\n});"
  },
  {
    "path": "chapter7/recipe4/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter7/recipe4/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <div ng-controller=\"User\">\n      <form name=\"form\" ng-submit=\"submit()\" novalidate>\n        <div class=\"control-group\" ng-class=\"error('firstname')\">\n          <label class=\"control-label\" for=\"firstname\">Firstname</label>\n          <div class=\"controls\">\n            <input id=\"firstname\" name=\"firstname\" type=\"text\" ng-model=\"user.firstname\" placeholder=\"Firstname\" required/>\n            <span class=\"help-block\" ng-show=\"form.firstname.$invalid && form.firstname.$dirty\">Firstname is required</span>\n          </div>\n        </div>\n\n        <div class=\"control-group\" ng-class=\"error('lastname')\">\n          <label class=\"control-label\" for=\"lastname\">Lastname</label>\n          <div class=\"controls\">\n            <input id=\"lastname\" name=\"lastname\" type=\"text\" ng-model=\"user.lastname\" placeholder=\"Lastname\" required/>\n            <span class=\"help-block\" ng-show=\"form.lastname.$invalid && form.lastname.$dirty\">Lastname is required</span>\n          </div>\n        </div>\n\n        <div class=\"control-group\">\n          <div class=\"controls\">\n            <button ng-disabled=\"form.$invalid\" class=\"btn\">Submit</button>\n          </div>\n        </div>\n      </form>\n\n      User Model: {{user}}\n      <br>\n      Form was submitted: {{wasSubmitted}}\n      <br>\n      Firstname input valid: {{form.firstname.$valid}}\n      <br>\n      Firstname validation error: {{form.firstname.$error}}\n      <br>\n      Form valid: {{form.$valid}}\n      <br>\n      Form validation error: {{form.$error}}\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter7/recipe4/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter7/recipe4/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.controller(\"User\", function($scope) {\n  $scope.user = {};\n  $scope.wasSubmitted = false;\n\n  $scope.submit = function() {\n    $scope.wasSubmitted = true;\n  };\n\n  $scope.error = function(name) {\n    var s = $scope.form[name];\n    return s.$invalid && s.$dirty ? \"error\" : \"\";\n  };\n});"
  },
  {
    "path": "chapter7/recipe5/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter7/recipe5/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n    <style type=\"text/css\">\n      input.ng-invalid.ng-dirty {\n        background-color: red;\n      }\n      input.ng-valid.ng-dirty {\n        background-color: green;\n      }\n    </style>\n  </head>\n  <body ng-app=\"MyApp\">\n    <div ng-controller=\"User\">\n      <form name=\"form\" ng-submit=\"submit()\" class=\"form-horizontal\" novalidate novalidate>\n        <label>Firstname</label>\n        <input name=\"firstname\" type=\"text\" ng-model=\"user.firstname\" required/>\n        <p ng-show=\"form.firstname.$invalid && form.firstname.$dirty\">Firstname is required</p>\n        <label>Lastname</label>\n        <input type=\"text\" ng-model=\"user.lastname\" required/>\n        <label>Age</label>\n        <input type=\"text\" ng-model=\"user.age\"/>\n        <br>\n        <button ng-disabled=\"form.$invalid\" class=\"btn\">Submit</button>\n      </form>\n\n      User Model: {{user}}\n      <br>\n      Form was submitted: {{wasSubmitted}}\n      <br>\n      Firstname input valid: {{form.firstname.$valid}}\n      <br>\n      Firstname validation error: {{form.firstname.$error}}\n      <br>\n      Form valid: {{form.$valid}}\n      <br>\n      Form validation error: {{form.$error}}\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter7/recipe5/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter7/recipe5/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.controller(\"User\", function($scope) {\n  $scope.user = {};\n  $scope.wasSubmitted = false;\n\n  $scope.submit = function() {\n    $scope.wasSubmitted = true;\n  };\n});"
  },
  {
    "path": "chapter7/recipe6/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter7/recipe6/index.html",
    "content": "<html>\n  <head>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/angular-ui.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n    <style type=\"text/css\">\n      input.ng-invalid.ng-dirty {\n        background-color: red;\n      }\n      input.ng-valid.ng-dirty {\n        background-color: green;\n      }\n    </style>\n  </head>\n  <body ng-app=\"MyApp\">\n    <div ng-controller=\"User\">\n      <form name=\"form\" ng-submit=\"submit()\" class=\"form-horizontal\" novalidate>\n        <label>Firstname</label>\n        <input name=\"firstname\" type=\"text\" ng-model=\"user.firstname\" required ui-validate=\" { blacklisted: 'notBlackListed($value)' } \"/>\n        <p ng-show=\"form.firstname.$invalid && form.firstname.$dirty\">Firstname is required</p>\n        <p ng-show='form.firstname.$error.blacklisted'>This firstname is blacklisted.</p>\n        <br>\n        <button ng-disabled=\"form.$invalid\" class=\"btn\">Submit</button>\n      </form>\n\n      User Model: {{user}}\n      <br>\n      Form was submitted: {{wasSubmitted}}\n      <br>\n      Firstname input valid: {{form.firstname.$valid}}\n      <br>\n      Firstname validation error: {{form.firstname.$error}}\n      <br>\n      Form valid: {{form.$valid}}\n      <br>\n      Form validation error: {{form.$error}}\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "chapter7/recipe6/js/angular-ui.js",
    "content": "/**\n * AngularUI - The companion suite for AngularJS\n * @version v0.3.2 - 2013-01-30\n * @link http://angular-ui.github.com\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\n\n\nangular.module('ui.config', []).value('ui.config', {});\nangular.module('ui.filters', ['ui.config']);\nangular.module('ui.directives', ['ui.config']);\nangular.module('ui', ['ui.filters', 'ui.directives', 'ui.config']);\n\n/**\n * General-purpose validator for ngModel.\n * angular.js comes with several built-in validation mechanism for input fields (ngRequired, ngPattern etc.) but using\n * an arbitrary validation function requires creation of a custom formatters and / or parsers.\n * The ui-validate directive makes it easy to use any function(s) defined in scope as a validator function(s).\n * A validator function will trigger validation on both model and input changes.\n *\n * @example <input ui-validate=\" 'myValidatorFunction($value)' \">\n * @example <input ui-validate=\"{ foo : '$value > anotherModel', bar : 'validateFoo($value)' }\">\n * @example <input ui-validate=\"{ foo : '$value > anotherModel' }\" ui-validate-watch=\" 'anotherModel' \">\n * @example <input ui-validate=\"{ foo : '$value > anotherModel', bar : 'validateFoo($value)' }\" ui-validate-watch=\" { foo : 'anotherModel' } \">\n *\n * @param ui-validate {string|object literal} If strings is passed it should be a scope's function to be used as a validator.\n * If an object literal is passed a key denotes a validation error key while a value should be a validator function.\n * In both cases validator function should take a value to validate as its argument and should return true/false indicating a validation result.\n */\nangular.module('ui.directives').directive('uiValidate', function () {\n\n  return {\n    restrict: 'A',\n    require: 'ngModel',\n    link: function (scope, elm, attrs, ctrl) {\n      var validateFn, watch, validators = {},\n        validateExpr = scope.$eval(attrs.uiValidate);\n\n      if (!validateExpr) return;\n\n      if (angular.isString(validateExpr)) {\n        validateExpr = { validator: validateExpr };\n      }\n\n      angular.forEach(validateExpr, function (expression, key) {\n        validateFn = function (valueToValidate) {\n          if (scope.$eval(expression, { '$value' : valueToValidate })) {\n            ctrl.$setValidity(key, true);\n            return valueToValidate;\n          } else {\n            ctrl.$setValidity(key, false);\n            return undefined;\n          }\n        };\n        validators[key] = validateFn;\n        ctrl.$formatters.push(validateFn);\n        ctrl.$parsers.push(validateFn);\n      });\n\n      // Support for ui-validate-watch\n      if (attrs.uiValidateWatch) {\n        watch = scope.$eval(attrs.uiValidateWatch);\n        if (angular.isString(watch)) {\n          scope.$watch(watch, function(){\n            angular.forEach(validators, function(validatorFn, key){\n              validatorFn(ctrl.$modelValue);\n            });\n          });\n        } else {\n          angular.forEach(watch, function(expression, key){\n            scope.$watch(expression, function(){\n              validators[key](ctrl.$modelValue);\n            });\n          });\n        }\n      }\n    }\n  };\n});\n"
  },
  {
    "path": "chapter7/recipe6/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter7/recipe6/js/app.js",
    "content": "var app = angular.module(\"MyApp\", [\"ui\", \"ui.directives\"]);\n\napp.controller(\"User\", function($scope) {\n  $scope.user = {};\n  $scope.wasSubmitted = false;\n\n  $scope.blacklist = ['idiot','loser'];\n\n  $scope.notBlackListed = function(value) {\n    return $scope.blacklist.indexOf(value) === -1;\n  };\n\n  $scope.submit = function() {\n    $scope.wasSubmitted = true;\n  };\n});"
  },
  {
    "path": "chapter8/recipe1/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter8/recipe1/index.html",
    "content": "<html>\n  <head>\n    <meta charset='utf-8'>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <div ng-controller=\"MyCtrl\">\n\n      <h3>Filter by String</h3>\n      <form class=\"form-inline\">\n        <input ng-model=\"query\" type=\"text\" placeholder=\"Filter by name\" autofocus>\n      </form>\n      <ul ng-repeat=\"friend in friends | filter: query | orderBy: 'name' \">\n        <li>{{friend.name}} ({{friend.age}})</li>\n      </ul>\n    </div>\n\n    <div ng-controller=\"MyCtrl\">\n      <h3>Filter by Object</h3>\n      <form class=\"form-inline\">\n        <input ng-model=\"query\" type=\"text\" placeholder=\"Filter by name and age=20\">\n      </form>\n      <ul ng-repeat=\"friend in friends | filter: { name: query, age: '20' } | orderBy: 'name' \">\n        <li>{{friend.name}} ({{friend.age}})</li>\n      </ul>\n    </div>\n\n    <div ng-controller=\"MyCtrl\">\n      <h3>Filter by Predicate Function</h3>\n      <ul ng-repeat=\"friend in friends | filter: filterFunction | orderBy: 'name' \">\n        <li>{{friend.name}} ({{friend.age}})</li>\n      </ul>\n    </div>\n  </body>\n</html>"
  },
  {
    "path": "chapter8/recipe1/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter8/recipe1/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.controller(\"MyCtrl\", function($scope) {\n  $scope.friends = [\n    { name: \"Peter\",   age: 20 },\n    { name: \"Pablo\",   age: 55 },\n    { name: \"Linda\",   age: 20 },\n    { name: \"Marta\",   age: 37 },\n    { name: \"Othello\", age: 20 },\n    { name: \"Markus\",  age: 32 }\n  ];\n\n  $scope.filterFunction = function(element) {\n    return element.name.match(/^Ma/) ? true : false;\n  };\n\n});"
  },
  {
    "path": "chapter8/recipe2/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter8/recipe2/index.html",
    "content": "<html>\n  <head>\n    <meta charset='utf-8'>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <div ng-controller=\"PaginationCtrl\">\n      <table class=\"table table-striped\">\n        <thead>\n          <tr>\n            <th>Id</th>\n            <th>Name</th>\n            <th>Description</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr ng-repeat=\"item in items | offset: currentPage*itemsPerPage | limitTo: itemsPerPage\">\n            <td>{{item.id}}</td>\n            <td>{{item.name}}</td>\n            <td>{{item.description}}</td>\n          </tr>\n        </tbody>\n        <tfoot>\n          <td colspan=\"3\">\n            <div class=\"pagination\">\n              <ul>\n                <li ng-class=\"prevPageDisabled()\">\n                  <a href ng-click=\"prevPage()\">« Prev</a>\n                </li>\n                <li ng-repeat=\"n in range()\" ng-class=\"{active: n == currentPage}\" ng-click=\"setPage(n)\">\n                  <a href=\"#\">{{n+1}}</a>\n                </li>\n                <li ng-class=\"nextPageDisabled()\">\n                  <a href ng-click=\"nextPage()\">Next »</a>\n                </li>\n              </ul>\n            </div>\n          </td>\n        </tfoot>\n      </table>\n    </div>\n  </body>\n</html>"
  },
  {
    "path": "chapter8/recipe2/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter8/recipe2/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.filter('offset', function() {\n  return function(input, start) {\n    start = parseInt(start, 10);\n    return input.slice(start);\n  };\n});\n\napp.controller(\"PaginationCtrl\", function($scope) {\n\n  $scope.itemsPerPage = 5;\n  $scope.currentPage = 0;\n  $scope.items = [];\n\n  for (var i=0; i<50; i++) {\n    $scope.items.push({ id: i, name: \"name \"+ i, description: \"description \" + i });\n  }\n\n  $scope.range = function() {\n    var rangeSize = 5;\n    var ret = [];\n    var start;\n\n    start = $scope.currentPage;\n    if ( start > $scope.pageCount()-rangeSize ) {\n      start = $scope.pageCount()-rangeSize+1;\n    }\n\n    for (var i=start; i<start+rangeSize; i++) {\n      ret.push(i);\n    }\n    return ret;\n  };\n\n  $scope.prevPage = function() {\n    if ($scope.currentPage > 0) {\n      $scope.currentPage--;\n    }\n  };\n\n  $scope.prevPageDisabled = function() {\n    return $scope.currentPage === 0 ? \"disabled\" : \"\";\n  };\n\n  $scope.pageCount = function() {\n    return Math.ceil($scope.items.length/$scope.itemsPerPage)-1;\n  };\n\n  $scope.nextPage = function() {\n    if ($scope.currentPage < $scope.pageCount()) {\n      $scope.currentPage++;\n    }\n  };\n\n  $scope.nextPageDisabled = function() {\n    return $scope.currentPage === $scope.pageCount() ? \"disabled\" : \"\";\n  };\n\n  $scope.setPage = function(n) {\n    $scope.currentPage = n;\n  };\n\n});"
  },
  {
    "path": "chapter8/recipe3/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter8/recipe3/index.html",
    "content": "<html>\n  <head>\n    <meta charset='utf-8'>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <div ng-controller=\"PaginationCtrl\">\n      <table class=\"table table-striped\">\n        <thead>\n          <tr>\n            <th>Id</th>\n            <th>Name</th>\n            <th>Description</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr ng-repeat=\"item in pagedItems\">\n            <td>{{item.id}}</td>\n            <td>{{item.name}}</td>\n            <td>{{item.description}}</td>\n          </tr>\n        </tbody>\n        <tfoot>\n          <td colspan=\"3\">\n            <div class=\"pagination\">\n              <ul>\n                <li ng-class=\"prevPageDisabled()\">\n                  <a href ng-click=\"prevPage()\">« Prev</a>\n                </li>\n                <li ng-repeat=\"n in range()\" ng-class=\"{active: n == currentPage}\" ng-click=\"setPage(n)\">\n                  <a href=\"#\">{{n+1}}</a>\n                </li>\n                <li ng-class=\"nextPageDisabled()\">\n                  <a href ng-click=\"nextPage()\">Next »</a>\n                </li>\n              </ul>\n            </div>\n          </td>\n        </tfoot>\n      </table>\n    </div>\n  </body>\n</html>"
  },
  {
    "path": "chapter8/recipe3/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter8/recipe3/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.factory(\"Item\", function() {\n\n  var items = [];\n  for (var i=0; i<50; i++) {\n    items.push({ id: i, name: \"name \"+ i, description: \"description \" + i });\n  }\n\n  return {\n    get: function(offset, limit) {\n      return items.slice(offset, offset+limit);\n    },\n    total: function() {\n      return items.length;\n    }\n  };\n});\n\napp.controller(\"PaginationCtrl\", function($scope, Item) {\n\n  $scope.itemsPerPage = 5;\n  $scope.currentPage = 0;\n\n  $scope.range = function() {\n    var rangeSize = 5;\n    var ret = [];\n    var start;\n\n    start = $scope.currentPage;\n    if ( start > $scope.pageCount()-rangeSize ) {\n      start = $scope.pageCount()-rangeSize;\n    }\n\n    for (var i=start; i<start+rangeSize; i++) {\n      ret.push(i);\n    }\n    return ret;\n  };\n\n\n  $scope.prevPage = function() {\n    if ($scope.currentPage > 0) {\n      $scope.currentPage--;\n    }\n  };\n\n  $scope.prevPageDisabled = function() {\n    return $scope.currentPage === 0 ? \"disabled\" : \"\";\n  };\n\n  $scope.nextPage = function() {\n    if ($scope.currentPage < $scope.pageCount() - 1) {\n      $scope.currentPage++;\n    }\n  };\n\n  $scope.nextPageDisabled = function() {\n    return $scope.currentPage === $scope.pageCount() - 1 ? \"disabled\" : \"\";\n  };\n\n  $scope.pageCount = function() {\n    return Math.ceil($scope.total/$scope.itemsPerPage);\n  };\n\n  $scope.setPage = function(n) {\n    if (n > 0 && n < $scope.pageCount()) {\n      $scope.currentPage = n;\n    }\n  };\n\n  $scope.$watch(\"currentPage\", function(newValue, oldValue) {\n    $scope.pagedItems = Item.get(newValue*$scope.itemsPerPage, $scope.itemsPerPage);\n    $scope.total = Item.total();\n  });\n\n});"
  },
  {
    "path": "chapter8/recipe4/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter8/recipe4/index.html",
    "content": "<html>\n  <head>\n    <meta charset='utf-8'>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\">\n    <div ng-controller=\"PaginationCtrl\">\n      <table class=\"table table-striped\">\n        <thead>\n          <tr>\n            <th>Id</th>\n            <th>Name</th>\n            <th>Description</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr ng-repeat=\"item in pagedItems\">\n            <td>{{item.id}}</td>\n            <td>{{item.name}}</td>\n            <td>{{item.description}}</td>\n          </tr>\n        </tbody>\n        <tfoot>\n          <td colspan=\"3\">\n            <button class=\"btn\" href=\"#\" ng-class=\"nextPageDisabledClass()\" ng-click=\"loadMore()\">Load More</button>\n          </td>\n        </tfoot>\n      </table>\n    </div>\n  </body>\n</html>"
  },
  {
    "path": "chapter8/recipe4/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter8/recipe4/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.factory(\"Item\", function() {\n\n  var items = [];\n  for (var i=0; i<50; i++) {\n    items.push({ id: i, name: \"name \"+ i, description: \"description \" + i });\n  }\n\n  return {\n    get: function(offset, limit) {\n      return items.slice(offset, offset+limit);\n    },\n    total: function() {\n      return items.length;\n    }\n  };\n});\n\napp.controller(\"PaginationCtrl\", function($scope, Item) {\n\n  $scope.itemsPerPage = 5;\n  $scope.currentPage = 0;\n  $scope.total = Item.total();\n  $scope.pagedItems = Item.get($scope.currentPage*$scope.itemsPerPage, $scope.itemsPerPage);\n\n  $scope.loadMore = function() {\n    $scope.currentPage++;\n    var newItems = Item.get($scope.currentPage*$scope.itemsPerPage, $scope.itemsPerPage);\n    $scope.pagedItems = $scope.pagedItems.concat(newItems);\n  };\n\n  $scope.nextPageDisabledClass = function() {\n    return $scope.currentPage === $scope.pageCount()-1 ? \"disabled\" : \"\";\n  };\n\n  $scope.pageCount = function() {\n    return Math.ceil($scope.total/$scope.itemsPerPage);\n  };\n\n});"
  },
  {
    "path": "chapter8/recipe5/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter8/recipe5/index.html",
    "content": "<html>\n  <head>\n    <meta charset='utf-8'>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n\n  </head>\n  <body ng-app=\"MyApp\" ng-controller=\"MyCtrl\">\n\n    <ul class=\"nav nav-pills\">\n      <li><a href=\"#/\">Home</a></li>\n      <li><a href=\"#/page\">Next Page</a></li>\n    </ul>\n\n    <div class=\"alert\" ng-show=\"flash.getMessage()\">\n      <b>Alert!</b>\n      <p>{{flash.getMessage()}}</p>\n    </div>\n\n    <ng-view></ng-view>\n\n    <script type=\"text/ng-template\" id=\"home.html\">\n      <h3>Home</h3>\n\n      <form ng-submit=\"submit(message)\" class=\"form-inline\">\n        <input type=\"text\" ng-model=\"message\" autofocus>\n        <button class=\"btn\">Submit</button>\n      </form>\n\n    </script>\n\n    <script type=\"text/ng-template\" id=\"page.html\">\n      <h3>Next Page</h3>\n\n    </script>\n\n  </body>\n</html>"
  },
  {
    "path": "chapter8/recipe5/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter8/recipe5/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.config(function($routeProvider) {\n  $routeProvider.\n    when(\"/home\", { templateUrl: \"home.html\" }).\n    when(\"/page\", { templateUrl: \"page.html\" }).\n    otherwise({ redirectTo: \"/home\" });\n});\n\napp.factory(\"flash\", function($rootScope) {\n  var queue = [];\n  var currentMessage = \"\";\n\n  $rootScope.$on(\"$routeChangeSuccess\", function() {\n    currentMessage = queue.shift() || \"\";\n  });\n\n  return {\n    setMessage: function(message) {\n      queue.push(message);\n    },\n    getMessage: function() {\n      return currentMessage;\n    }\n  };\n});\n\napp.controller(\"MyCtrl\", function($scope, $location, flash) {\n  $scope.flash = flash;\n  $scope.message = \"Hello World\";\n\n  $scope.submit = function(message) {\n    flash.setMessage(message);\n    $location.path(\"/page\");\n  }\n});"
  },
  {
    "path": "chapter8/recipe6/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter8/recipe6/index.html",
    "content": "<html>\n  <head>\n    <meta charset='utf-8'>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n    <style>\n      [contenteditable] {\n        border: 2px dotted #ccc;\n        background-color: #eee;\n        padding: 2px;\n      }\n    </style>\n  </head>\n  <body ng-app=\"MyApp\">\n    <div contenteditable ng-model=\"text\"></div>\n    <br>\n    <p>{{text}}</p>\n  </body>\n</html>"
  },
  {
    "path": "chapter8/recipe6/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter8/recipe6/js/app.js",
    "content": "var app = angular.module(\"MyApp\", []);\n\napp.directive(\"contenteditable\", function() {\n  return {\n    restrict: \"A\",\n    require: \"ngModel\",\n    link: function(scope, element, attrs, ngModel) {\n\n      function read() {\n        ngModel.$setViewValue(element.html());\n      }\n\n      ngModel.$render = function() {\n        element.html(ngModel.$viewValue || \"\");\n      };\n\n      element.bind(\"blur keyup change\", function() {\n        scope.$apply(read);\n      });\n    }\n  };\n});"
  },
  {
    "path": "chapter8/recipe7/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter8/recipe7/index.html",
    "content": "<html>\n  <head>\n    <meta charset='utf-8'>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/angular-ui-bootstrap-modal.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n  </head>\n  <body ng-app=\"MyApp\" ng-controller=\"MyCtrl\">\n\n    <button class=\"btn\" ng-click=\"open()\">Open Modal</button>\n\n    <div modal=\"showModal\" close=\"cancel()\">\n      <div class=\"modal-header\">\n          <h4>Modal Dialog</h4>\n      </div>\n      <div class=\"modal-body\">\n          <p>Example paragraph with some text.</p>\n      </div>\n      <div class=\"modal-footer\">\n        <button class=\"btn btn-success\" ng-click=\"ok()\">Okay</button>\n        <button class=\"btn\" ng-click=\"cancel()\">Cancel</button>\n      </div>\n    </div>\n\n  </body>\n</html>"
  },
  {
    "path": "chapter8/recipe7/js/angular-ui-bootstrap-modal.js",
    "content": "angular.module('ui.bootstrap.modal', [])\n.constant('modalConfig', {\n  backdrop: true,\n  escape: true\n})\n.directive('modal', ['$parse', 'modalConfig', function($parse, modalConfig) {\n  var backdropEl;\n  var body = angular.element(document.getElementsByTagName('body')[0]);\n  return {\n    restrict: 'EA',\n    link: function(scope, elm, attrs) {\n      var opts = angular.extend({}, modalConfig, scope.$eval(attrs.uiOptions || attrs.bsOptions || attrs.options));\n      var shownExpr = attrs.modal || attrs.show;\n      var setClosed;\n\n      if (attrs.close) {\n        setClosed = function() {\n          scope.$apply(attrs.close);\n        };\n      } else {\n        setClosed = function() {\n          scope.$apply(function() {\n            $parse(shownExpr).assign(scope, false);\n          });\n        };\n      }\n      elm.addClass('modal');\n\n      if (opts.backdrop && !backdropEl) {\n        backdropEl = angular.element('<div class=\"modal-backdrop\"></div>');\n        backdropEl.css('display','none');\n        body.append(backdropEl);\n      }\n\n      function setShown(shown) {\n        scope.$apply(function() {\n          model.assign(scope, shown);\n        });\n      }\n\n      function escapeClose(evt) {\n        if (evt.which === 27) { setClosed(); }\n      }\n      function clickClose() {\n        setClosed();\n      }\n\n      function close() {\n        if (opts.escape) { body.unbind('keyup', escapeClose); }\n        if (opts.backdrop) {\n          backdropEl.css('display', 'none').removeClass('in');\n          backdropEl.unbind('click', clickClose);\n        }\n        elm.css('display', 'none').removeClass('in');\n        body.removeClass('modal-open');\n      }\n      function open() {\n        if (opts.escape) { body.bind('keyup', escapeClose); }\n        if (opts.backdrop) {\n          backdropEl.css('display', 'block').addClass('in');\n          if(opts.backdrop != \"static\") {\n            backdropEl.bind('click', clickClose);\n          }\n        }\n        elm.css('display', 'block').addClass('in');\n        body.addClass('modal-open');\n      }\n\n      scope.$watch(shownExpr, function(isShown, oldShown) {\n        if (isShown) {\n          open();\n        } else {\n          close();\n        }\n      });\n    }\n  };\n}]);"
  },
  {
    "path": "chapter8/recipe7/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter8/recipe7/js/app.js",
    "content": "var app = angular.module(\"MyApp\", [\"ui.bootstrap.modal\"]);\n\napp.controller(\"MyCtrl\", function($scope) {\n\n  $scope.open = function() {\n    $scope.showModal = true;\n  };\n\n  $scope.ok = function() {\n    $scope.showModal = false;\n  };\n\n  $scope.cancel = function() {\n    $scope.showModal = false;\n  };\n\n});\n\n"
  },
  {
    "path": "chapter8/recipe8/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.2.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 0.5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover {\n  color: #356635;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\n}\n\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  overflow: hidden;\n  clear: left;\n  text-align: right;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\nform {\n  margin: 0 0 20px;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\n\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  *padding-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\n}\n\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.pager li > a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > span {\n  color: #999999;\n  cursor: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.tooltip.top {\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media .pull-left {\n  margin-right: 10px;\n}\n\n.media .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress .bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n.accordion-toggle {\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n     -moz-transition: 0.6s ease-in-out left;\n       -o-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img {\n  display: block;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\n}\n\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "chapter8/recipe8/index.html",
    "content": "<html>\n  <head>\n    <meta charset='utf-8'>\n    <script src=\"http://code.jquery.com/jquery.min.js\"></script>\n    <script src=\"js/angular.js\"></script>\n    <script src=\"js/angular-resource.js\"></script>\n    <script src=\"js/app.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/bootstrap.css\">\n    <style>\n      li { list-style: none; }\n    </style>\n  </head>\n  <body ng-app=\"MyApp\" ng-controller=\"MyCtrl\">\n\n    <div>\n      <button class=\"btn\" ng-click=\"load()\">Load Tweets</button>\n      <img id=\"spinner\" ng-src=\"img/spinner.gif\" style=\"display:none;\">\n    </div>\n\n    <div>\n      <ul ng-repeat=\"tweet in tweets\">\n        <li>\n          <img ng-src=\"{{tweet.profile_image_url}}\" alt=\"\"> &nbsp; {{tweet.from_user}}\n          {{tweet.text}}\n        </li>\n      </ul>\n    </div>\n\n  </body>\n</html>"
  },
  {
    "path": "chapter8/recipe8/js/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g.\n *   `http://example.com:8080/api`), you'll need to escape the colon character before the port\n *   number, like this: `$resource('http://example.com\\\\:8080/api')`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` â€“ {string} â€“ The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` â€“ {string} â€“ HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` â€“ {object=} â€“ Optional set of pre-bound parameters for this action.\n *   - isArray â€“ {boolean=} â€“ If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class `save`, `remove` and `delete` actions are available on it as\n *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,\n *   update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n *     It's worth noting that the success callback for `get`, `query` and other method gets passed\n *     in the response that came from the server as well as $http header getter function, so one\n *     could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n     * encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace((pctEncodeSpaces ? null : /%20/g), '+');\n    }\n\n    function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && template.match(new RegExp(\"[^\\\\\\\\]:\" + param + \"\\\\W\"))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        action.method = angular.uppercase(action.method);\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);"
  },
  {
    "path": "chapter8/recipe8/js/angular.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar Error             = window.Error,\n    /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isObject(obj) && isNumber(obj.length)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      while(destination.length) {\n        destination.pop();\n      }\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  return jqLite('<div>').append(element).html().\n      match(/^(<[^>]+>)/)[1].\n      replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * ot the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.4',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 4,\n  codeName: 'bewildering-hair'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$injector` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : href;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n        $linkNode.data('$scope', scope);\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context`: an object against which any expressions embedded in the strings are evaluated\n *      against (Topically a scope object).\n *    * `locals`: local variables context object, useful for overriding values in `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise apis are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as apis\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and it's value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n * \n *  # Testing\n * \n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootSCope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n * \n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Simulate resolving of promise\n *      defered.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n * \n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with on object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value coresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's uniqueue we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          completeRequest(\n              callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!(array instanceof Array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var offset = date.getTimezoneOffset();\n  return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} \\-?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(array instanceof Array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * <a href=\"\" ng-click=\"model.$save()\">Save</a>\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    // turn <a href ng-click=\"..\">link</a> into a link in IE\n    // but only if it doesn't have name attribute, in which case it's an anchor\n    if (!attr.href) {\n      attr.$set('href', '');\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe('');\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect\n          if (msie) element.prop(attrName, value);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal, oldVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the classes\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  controller: function ngSwitchController() {\n    this.cases = {};\n  },\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.contents().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter8/recipe8/js/app.js",
    "content": "var app = angular.module(\"MyApp\", [\"ngResource\"]);\n\napp.config(function ($httpProvider) {\n  $httpProvider.responseInterceptors.push('myHttpInterceptor');\n\n  var spinnerFunction = function spinnerFunction(data, headersGetter) {\n    $(\"#spinner\").show();\n    return data;\n  };\n\n  $httpProvider.defaults.transformRequest.push(spinnerFunction);\n});\n\napp.factory('myHttpInterceptor', function ($q, $window) {\n  return function (promise) {\n    return promise.then(function (response) {\n      $(\"#spinner\").hide();\n      return response;\n    }, function (response) {\n      $(\"#spinner\").hide();\n      return $q.reject(response);\n    });\n  };\n});\n\napp.controller(\"MyCtrl\", function($scope, $resource, $rootScope) {\n\n  $scope.resultsPerPage = 5;\n  $scope.page = 1;\n  $scope.searchTerm = \"angularjs\";\n\n  $scope.twitter = $resource('http://search.twitter.com/search.json',\n    { callback:'JSON_CALLBACK', page: $scope.page, rpp: $scope.resultsPerPage, q: $scope.searchTerm },\n    { get: { method:'JSONP' } });\n\n  $scope.load = function() {\n    $scope.twitter.get(function(data) {\n      $scope.tweets = data.results;\n    });\n  };\n});"
  },
  {
    "path": "chapter9/recipe1/contacts/.gitignore",
    "content": "# See http://help.github.com/ignore-files/ for more about ignoring files.\n#\n# If you find yourself ignoring temporary files generated by your text editor\n# or operating system, you probably want to add a global ignore instead:\n#   git config --global core.excludesfile ~/.gitignore_global\n\n# Ignore bundler config\n/.bundle\n\n# Ignore the default SQLite database.\n/db/*.sqlite3\n\n# Ignore all logfiles and tempfiles.\n/log/*.log\n/tmp\n"
  },
  {
    "path": "chapter9/recipe1/contacts/Gemfile",
    "content": "source 'https://rubygems.org'\n\ngem 'rails', '3.2.11'\n\n# Bundle edge Rails instead:\n# gem 'rails', :git => 'git://github.com/rails/rails.git'\n\ngem 'sqlite3'\n\n\n# Gems used only for assets and not required\n# in production environments by default.\ngroup :assets do\n  gem 'sass-rails',   '~> 3.2.3'\n  gem 'coffee-rails', '~> 3.2.1'\n\n  # See https://github.com/sstephenson/execjs#readme for more supported runtimes\n  gem 'therubyracer', :platforms => :ruby\n\n  gem 'uglifier', '>= 1.0.3'\nend\n\ngem 'jquery-rails'\n\n# gem \"less-rails\"\ngem \"twitter-bootstrap-rails\"\n\n# To use ActiveModel has_secure_password\n# gem 'bcrypt-ruby', '~> 3.0.0'\n\n# To use Jbuilder templates for JSON\n# gem 'jbuilder'\n\n# Use unicorn as the app server\n# gem 'unicorn'\n\n# Deploy with Capistrano\n# gem 'capistrano'\n\n# To use debugger\n# gem 'debugger'\n"
  },
  {
    "path": "chapter9/recipe1/contacts/README.rdoc",
    "content": "== Welcome to Rails\n\nRails is a web-application framework that includes everything needed to create\ndatabase-backed web applications according to the Model-View-Control pattern.\n\nThis pattern splits the view (also called the presentation) into \"dumb\"\ntemplates that are primarily responsible for inserting pre-built data in between\nHTML tags. The model contains the \"smart\" domain objects (such as Account,\nProduct, Person, Post) that holds all the business logic and knows how to\npersist themselves to a database. The controller handles the incoming requests\n(such as Save New Account, Update Product, Show Post) by manipulating the model\nand directing data to the view.\n\nIn Rails, the model is handled by what's called an object-relational mapping\nlayer entitled Active Record. This layer allows you to present the data from\ndatabase rows as objects and embellish these data objects with business logic\nmethods. You can read more about Active Record in\nlink:files/vendor/rails/activerecord/README.html.\n\nThe controller and view are handled by the Action Pack, which handles both\nlayers by its two parts: Action View and Action Controller. These two layers\nare bundled in a single package due to their heavy interdependence. This is\nunlike the relationship between the Active Record and Action Pack that is much\nmore separate. Each of these packages can be used independently outside of\nRails. You can read more about Action Pack in\nlink:files/vendor/rails/actionpack/README.html.\n\n\n== Getting Started\n\n1. At the command prompt, create a new Rails application:\n       <tt>rails new myapp</tt> (where <tt>myapp</tt> is the application name)\n\n2. Change directory to <tt>myapp</tt> and start the web server:\n       <tt>cd myapp; rails server</tt> (run with --help for options)\n\n3. Go to http://localhost:3000/ and you'll see:\n       \"Welcome aboard: You're riding Ruby on Rails!\"\n\n4. Follow the guidelines to start developing your application. You can find\nthe following resources handy:\n\n* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html\n* Ruby on Rails Tutorial Book: http://www.railstutorial.org/\n\n\n== Debugging Rails\n\nSometimes your application goes wrong. Fortunately there are a lot of tools that\nwill help you debug it and get it back on the rails.\n\nFirst area to check is the application log files. Have \"tail -f\" commands\nrunning on the server.log and development.log. Rails will automatically display\ndebugging and runtime information to these files. Debugging info will also be\nshown in the browser on requests from 127.0.0.1.\n\nYou can also log your own messages directly into the log file from your code\nusing the Ruby logger class from inside your controllers. Example:\n\n  class WeblogController < ActionController::Base\n    def destroy\n      @weblog = Weblog.find(params[:id])\n      @weblog.destroy\n      logger.info(\"#{Time.now} Destroyed Weblog ID ##{@weblog.id}!\")\n    end\n  end\n\nThe result will be a message in your log file along the lines of:\n\n  Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!\n\nMore information on how to use the logger is at http://www.ruby-doc.org/core/\n\nAlso, Ruby documentation can be found at http://www.ruby-lang.org/. There are\nseveral books available online as well:\n\n* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)\n* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)\n\nThese two books will bring you up to speed on the Ruby language and also on\nprogramming in general.\n\n\n== Debugger\n\nDebugger support is available through the debugger command when you start your\nMongrel or WEBrick server with --debugger. This means that you can break out of\nexecution at any point in the code, investigate and change the model, and then,\nresume execution! You need to install ruby-debug to run the server in debugging\nmode. With gems, use <tt>sudo gem install ruby-debug</tt>. Example:\n\n  class WeblogController < ActionController::Base\n    def index\n      @posts = Post.all\n      debugger\n    end\n  end\n\nSo the controller will accept the action, run the first line, then present you\nwith a IRB prompt in the server window. Here you can do things like:\n\n  >> @posts.inspect\n  => \"[#<Post:0x14a6be8\n          @attributes={\"title\"=>nil, \"body\"=>nil, \"id\"=>\"1\"}>,\n       #<Post:0x14a6620\n          @attributes={\"title\"=>\"Rails\", \"body\"=>\"Only ten..\", \"id\"=>\"2\"}>]\"\n  >> @posts.first.title = \"hello from a debugger\"\n  => \"hello from a debugger\"\n\n...and even better, you can examine how your runtime objects actually work:\n\n  >> f = @posts.first\n  => #<Post:0x13630c4 @attributes={\"title\"=>nil, \"body\"=>nil, \"id\"=>\"1\"}>\n  >> f.\n  Display all 152 possibilities? (y or n)\n\nFinally, when you're ready to resume execution, you can enter \"cont\".\n\n\n== Console\n\nThe console is a Ruby shell, which allows you to interact with your\napplication's domain model. Here you'll have all parts of the application\nconfigured, just like it is when the application is running. You can inspect\ndomain models, change values, and save to the database. Starting the script\nwithout arguments will launch it in the development environment.\n\nTo start the console, run <tt>rails console</tt> from the application\ndirectory.\n\nOptions:\n\n* Passing the <tt>-s, --sandbox</tt> argument will rollback any modifications\n  made to the database.\n* Passing an environment name as an argument will load the corresponding\n  environment. Example: <tt>rails console production</tt>.\n\nTo reload your controllers and models after launching the console run\n<tt>reload!</tt>\n\nMore information about irb can be found at:\nlink:http://www.rubycentral.org/pickaxe/irb.html\n\n\n== dbconsole\n\nYou can go to the command line of your database directly through <tt>rails\ndbconsole</tt>. You would be connected to the database with the credentials\ndefined in database.yml. Starting the script without arguments will connect you\nto the development database. Passing an argument will connect you to a different\ndatabase, like <tt>rails dbconsole production</tt>. Currently works for MySQL,\nPostgreSQL and SQLite 3.\n\n== Description of Contents\n\nThe default directory structure of a generated Ruby on Rails application:\n\n  |-- app\n  |   |-- assets\n  |       |-- images\n  |       |-- javascripts\n  |       `-- stylesheets\n  |   |-- controllers\n  |   |-- helpers\n  |   |-- mailers\n  |   |-- models\n  |   `-- views\n  |       `-- layouts\n  |-- config\n  |   |-- environments\n  |   |-- initializers\n  |   `-- locales\n  |-- db\n  |-- doc\n  |-- lib\n  |   `-- tasks\n  |-- log\n  |-- public\n  |-- script\n  |-- test\n  |   |-- fixtures\n  |   |-- functional\n  |   |-- integration\n  |   |-- performance\n  |   `-- unit\n  |-- tmp\n  |   |-- cache\n  |   |-- pids\n  |   |-- sessions\n  |   `-- sockets\n  `-- vendor\n      |-- assets\n          `-- stylesheets\n      `-- plugins\n\napp\n  Holds all the code that's specific to this particular application.\n\napp/assets\n  Contains subdirectories for images, stylesheets, and JavaScript files.\n\napp/controllers\n  Holds controllers that should be named like weblogs_controller.rb for\n  automated URL mapping. All controllers should descend from\n  ApplicationController which itself descends from ActionController::Base.\n\napp/models\n  Holds models that should be named like post.rb. Models descend from\n  ActiveRecord::Base by default.\n\napp/views\n  Holds the template files for the view that should be named like\n  weblogs/index.html.erb for the WeblogsController#index action. All views use\n  eRuby syntax by default.\n\napp/views/layouts\n  Holds the template files for layouts to be used with views. This models the\n  common header/footer method of wrapping views. In your views, define a layout\n  using the <tt>layout :default</tt> and create a file named default.html.erb.\n  Inside default.html.erb, call <% yield %> to render the view using this\n  layout.\n\napp/helpers\n  Holds view helpers that should be named like weblogs_helper.rb. These are\n  generated for you automatically when using generators for controllers.\n  Helpers can be used to wrap functionality for your views into methods.\n\nconfig\n  Configuration files for the Rails environment, the routing map, the database,\n  and other dependencies.\n\ndb\n  Contains the database schema in schema.rb. db/migrate contains all the\n  sequence of Migrations for your schema.\n\ndoc\n  This directory is where your application documentation will be stored when\n  generated using <tt>rake doc:app</tt>\n\nlib\n  Application specific libraries. Basically, any kind of custom code that\n  doesn't belong under controllers, models, or helpers. This directory is in\n  the load path.\n\npublic\n  The directory available for the web server. Also contains the dispatchers and the\n  default HTML files. This should be set as the DOCUMENT_ROOT of your web\n  server.\n\nscript\n  Helper scripts for automation and generation.\n\ntest\n  Unit and functional tests along with fixtures. When using the rails generate\n  command, template test files will be generated for you and placed in this\n  directory.\n\nvendor\n  External libraries that the application depends on. Also includes the plugins\n  subdirectory. If the app has frozen rails, those gems also go here, under\n  vendor/rails/. This directory is in the load path.\n"
  },
  {
    "path": "chapter9/recipe1/contacts/Rakefile",
    "content": "#!/usr/bin/env rake\n# Add your own tasks in files placed in lib/tasks ending in .rake,\n# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.\n\nrequire File.expand_path('../config/application', __FILE__)\n\nContacts::Application.load_tasks\n"
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/javascripts/angular/app.js.erb",
    "content": "var app = angular.module(\"Contacts\", [\"ngResource\"]);\n\napp.config(function($routeProvider, $locationProvider) {\n  $locationProvider.html5Mode(true);\n  $routeProvider\n    .when(\"/contacts\", { templateUrl: \"<%= asset_path('contacts/index.html') %> \", controller: \"ContactsIndexCtrl\" })\n    .when(\"/contacts/new\", { templateUrl: \"<%= asset_path('contacts/edit.html') %> \", controller: \"ContactsEditCtrl\" })\n    .when(\"/contacts/:id\", { templateUrl: \"<%= asset_path('contacts/show.html') %> \", controller: \"ContactsShowCtrl\" })\n    .when(\"/contacts/:id/edit\", { templateUrl: \"<%= asset_path('contacts/edit.html') %> \", controller: \"ContactsEditCtrl\" })\n    .otherwise({ redirectTo: \"/contacts\" });\n});\n\napp.config(function($httpProvider) {\n  $httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content');\n});"
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/javascripts/angular/controllers/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/javascripts/angular/controllers/ContactsEditCtrl.js",
    "content": "app.controller(\"ContactsEditCtrl\", function($scope, $routeParams, $location, Contact) {\n\n  if ($routeParams.id) {\n    $scope.contact = Contact.show({ id: $routeParams.id });\n  } else {\n    $scope.contact = new Contact();\n  }\n\n  $scope.submit = function() {\n    console.log(\"submit\")\n\n    function success(response) {\n      console.log(\"success\", response)\n      $location.path(\"/contacts\");\n    }\n\n    function failure(response) {\n      console.log(\"failure\", response)\n\n      _.each(response.data, function(errors, key) {\n        _.each(errors, function(e) {\n          $scope.form[key].$dirty = true;\n          $scope.form[key].$setValidity(e, false);\n        });\n      });\n    }\n\n    if ($routeParams.id) {\n      Contact.update($scope.contact, success, failure);\n    } else {\n      Contact.create($scope.contact, success, failure);\n    }\n\n  };\n\n  $scope.cancel = function() {\n    $location.path(\"/contacts/\"+$scope.contact.id);\n  };\n\n  $scope.errorClass = function(name) {\n    var s = $scope.form[name];\n    return s.$invalid && s.$dirty ? \"error\" : \"\";\n  };\n\n  $scope.errorMessage = function(name) {\n    var s = $scope.form[name].$error;\n    result = [];\n    _.each(s, function(key, value) {\n      result.push(value);\n    });\n    return result.join(\", \");\n  };\n});"
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/javascripts/angular/controllers/ContactsIndexCtrl.js",
    "content": "app.controller(\"ContactsIndexCtrl\", function($scope, $location, Contact) {\n  $scope.contacts = Contact.index();\n\n  $scope.new = function() {\n    $location.path(\"/contacts/new\");\n  };\n});"
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/javascripts/angular/controllers/ContactsShowCtrl.js",
    "content": "app.controller(\"ContactsShowCtrl\", function($scope, $routeParams, Contact) {\n  $scope.contact = Contact.show({ id: $routeParams.id });\n});"
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/javascripts/angular/controllers/MainCtrl.js",
    "content": "app.controller(\"MainCtrl\", function($scope) {\n});"
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/javascripts/angular/filters/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/javascripts/angular/services/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/javascripts/angular/services/Contact.js",
    "content": "app.factory(\"Contact\", function($resource) {\n  return $resource(\"/api/contacts/:id\", { id: \"@id\" },\n    {\n      'create':  { method: 'POST' },\n      'index':   { method: 'GET', isArray: true },\n      'show':    { method: 'GET', isArray: false },\n      'update':  { method: 'PUT' },\n      'destroy': { method: 'DELETE' }\n    }\n  );\n});"
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/javascripts/application.js",
    "content": "// This is a manifest file that'll be compiled into application.js, which will include all the files\n// listed below.\n//\n// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,\n// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.\n//\n// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the\n// the compiled file.\n//\n// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD\n// GO AFTER THE REQUIRES BELOW.\n//\n//= require jquery\n//= require jquery_ujs\n//= require underscore\n//= require twitter/bootstrap\n//= require angular\n//= require angular-resource\n\n//= require ./angular/app\n//= require_tree ./angular"
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/stylesheets/application.css",
    "content": "/*\n * This is a manifest file that'll be compiled into application.css, which will include all the files\n * listed below.\n *\n * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,\n * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.\n *\n * You're free to add application-wide styles to this file and they'll appear at the top of the\n * compiled file, but it's generally better to create a new file per style scope.\n *\n *= require_self\n *= require_tree .\n */\n\n body {\n   padding-top: 50px;\n }\n\n footer {\n   margin-top: 20px;\n }"
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/stylesheets/bootstrap_and_overrides.css",
    "content": "/*\n  =require twitter-bootstrap-static/bootstrap\n\n  Use Font Awesome icons (default)\n  To use Glyphicons sprites instead of Font Awesome, replace with \"require twitter-bootstrap-static/sprites\"\n  =require twitter-bootstrap-static/fontawesome\n  */"
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/templates/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/templates/contacts/edit.html",
    "content": "<h3>Contact Details</h3>\n\n<form name=\"form\" ng-submit=\"submit()\" class=\"form-horizontal\" novalidate>\n\n  <div class=\"control-group\" ng-class=\"errorClass('firstname')\">\n    <label class=\"control-label\" for=\"firstname\">Firstname</label>\n    <div class=\"controls\">\n      <input ng-model=\"contact.firstname\" type=\"text\" name=\"firstname\"placeholder=\"Firstname\" required autofocus>\n    </div>\n  </div>\n\n  <div class=\"control-group\" ng-class=\"errorClass('lastname')\">\n    <label class=\"control-label\" for=\"lastname\">Lastname</label>\n    <div class=\"controls\">\n      <input ng-model=\"contact.lastname\" type=\"text\" name=\"lastname\" placeholder=\"Lastname\" required>\n    </div>\n  </div>\n\n  <div class=\"control-group\" ng-class=\"errorClass('age')\">\n    <label class=\"control-label\" for=\"age\">Age</label>\n    <div class=\"controls\">\n      <input ng-model=\"contact.age\" type=\"text\" name=\"age\" placeholder=\"Age\" required>\n      <span class=\"help-block\" ng-show=\"form.age.$invalid && form.age.$dirty\">\n        {{errorMessage('age')}}\n      </span>\n    </div>\n  </div>\n\n  <div class=\"control-group\">\n    <div class=\"controls\">\n      <a class=\"btn\" ng-click=\"cancel()\">Cancel</a>\n      <button type=\"submit\" class=\"btn btn-success\">Save</button>\n    </div>\n  </div>\n</form>\n\n<a href=\"/contacts/{{contact.id}}\">Back</a>\n"
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/templates/contacts/index.html",
    "content": "<h3>Contacts</h3>\n\n<table class=\"table table-striped\">\n  <thead>\n    <td>Id</td>\n    <td>First Name</td>\n    <td>Last Name</td>\n    <td>Age</td>\n    <td>Actions</td>\n  </thead>\n  <tbody>\n    <tr ng-repeat=\"contact in contacts\">\n      <td>\n        {{contact.id}}\n      </td>\n      <td>\n        {{contact.firstname}}\n      </td>\n      <td>\n        {{contact.lastname}}\n      </td>\n      <td>\n        {{contact.age}}\n      </td>\n      <td>\n        <a href=\"/contacts/{{contact.id}}\">Show</a> |\n        <a href=\"/contacts/{{contact.id}}/edit\">Edit</a>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n<button ng-click=\"new()\" class=\"btn btn-success\">New Contact</button>"
  },
  {
    "path": "chapter9/recipe1/contacts/app/assets/templates/contacts/show.html",
    "content": "<h3>Contact Details</h3>\n\n<div>\n  <h5>First Name</h5>\n  {{contact.firstname}}\n\n  <h5>Last Name</h5>\n  {{contact.lastname}}\n\n  <h5>Age</h5>\n  {{contact.age}}\n</div>\n\n<hr>\n<div>\n  <a href=\"/contacts\">Back</a> | <a href=\"/contacts/{{contact.id}}/edit\">Edit</a>\n</div>\n"
  },
  {
    "path": "chapter9/recipe1/contacts/app/controllers/application_controller.rb",
    "content": "class ApplicationController < ActionController::Base\n  protect_from_forgery\n\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/app/controllers/contacts_controller.rb",
    "content": "class ContactsController < ApplicationController\n  respond_to :json\n\n  def index\n    @contacts = Contact.all\n    respond_with @contacts\n  end\n\n  def show\n    @contact = Contact.find(params[:id])\n    respond_with @contact\n  end\n\n  def create\n    @contact = Contact.new(params[:contact])\n    if @contact.save\n      render json: @contact, status: :created, location: @contact\n    else\n      render json: @contact.errors, status: :unprocessable_entity\n    end\n  end\n\n  def update\n    @contact = Contact.find(params[:id])\n    if @contact.update_attributes(params[:contact])\n      head :no_content\n    else\n      render json: @contact.errors, status: :unprocessable_entity\n    end\n  end\n\n  def destroy\n    @contact = Contact.find(params[:id])\n    @contact.destroy\n    head :no_content\n  end\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/app/controllers/layouts_controller.rb",
    "content": "class LayoutsController < ApplicationController\n  def index\n    render \"layouts/application\"\n  end\nend"
  },
  {
    "path": "chapter9/recipe1/contacts/app/helpers/application_helper.rb",
    "content": "module ApplicationHelper\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/app/helpers/contacts_helper.rb",
    "content": "module ContactsHelper\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/app/mailers/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/app/models/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/app/models/contact.rb",
    "content": "class Contact < ActiveRecord::Base\n  attr_accessible :age, :firstname, :lastname\n\n  validates :age, :numericality => { :only_integer => true, :less_than_or_equal_to => 50 }\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/app/views/layouts/application.html.erb",
    "content": "<!DOCTYPE html>\n<html lang=\"en\" ng-app=\"Contacts\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=Edge,chrome=1\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title><%= content_for?(:title) ? yield(:title) : \"Contacts\" %></title>\n    <%= csrf_meta_tags %>\n\n    <!-- Le HTML5 shim, for IE6-8 support of HTML elements -->\n    <!--[if lt IE 9]>\n      <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.6.1/html5shiv.js\" type=\"text/javascript\"></script>\n    <![endif]-->\n\n    <%= stylesheet_link_tag \"application\", :media => \"all\" %>\n\n  </head>\n  <body ng-controller=\"MainCtrl\">\n\n    <div class=\"navbar navbar-fixed-top\">\n      <div class=\"navbar-inner\">\n        <div class=\"container\">\n          <a class=\"brand\" href=\"#\">Contacts</a>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"container\">\n      <div class=\"row\">\n        <div class=\"span12\">\n          <ng-view></ng-view>\n        </div>\n      </div><!--/row-->\n\n      <footer>\n        <p>&copy; Company 2012</p>\n      </footer>\n\n    </div> <!-- /container -->\n\n    <!-- Javascripts\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n    <%= javascript_include_tag \"application\" %>\n\n  </body>\n</html>\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/application.rb",
    "content": "require File.expand_path('../boot', __FILE__)\n\nrequire 'rails/all'\n\nif defined?(Bundler)\n  # If you precompile assets before deploying to production, use this line\n  Bundler.require(*Rails.groups(:assets => %w(development test)))\n  # If you want your assets lazily compiled in production, use this line\n  # Bundler.require(:default, :assets, Rails.env)\nend\n\nmodule Contacts\n  class Application < Rails::Application\n    # Settings in config/environments/* take precedence over those specified here.\n    # Application configuration should go into files in config/initializers\n    # -- all .rb files in that directory are automatically loaded.\n\n    # Custom directories with classes and modules you want to be autoloadable.\n    # config.autoload_paths += %W(#{config.root}/extras)\n\n    # Only load the plugins named here, in the order given (default is alphabetical).\n    # :all can be used as a placeholder for all plugins not explicitly named.\n    # config.plugins = [ :exception_notification, :ssl_requirement, :all ]\n\n    # Activate observers that should always be running.\n    # config.active_record.observers = :cacher, :garbage_collector, :forum_observer\n\n    # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.\n    # Run \"rake -D time\" for a list of tasks for finding time zone names. Default is UTC.\n    # config.time_zone = 'Central Time (US & Canada)'\n\n    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.\n    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]\n    # config.i18n.default_locale = :de\n\n    # Configure the default encoding used in templates for Ruby 1.9.\n    config.encoding = \"utf-8\"\n\n    # Configure sensitive parameters which will be filtered from the log file.\n    config.filter_parameters += [:password]\n\n    # Enable escaping HTML in JSON.\n    config.active_support.escape_html_entities_in_json = true\n\n    # Use SQL instead of Active Record's schema dumper when creating the database.\n    # This is necessary if your schema can't be completely dumped by the schema dumper,\n    # like if you have constraints or database-specific column types\n    # config.active_record.schema_format = :sql\n\n    # Enforce whitelist mode for mass assignment.\n    # This will create an empty whitelist of attributes available for mass-assignment for all models\n    # in your app. As such, your models will need to explicitly whitelist or blacklist accessible\n    # parameters by using an attr_accessible or attr_protected declaration.\n    config.active_record.whitelist_attributes = true\n\n    # Enable the asset pipeline\n    config.assets.enabled = true\n\n    # Version of your assets, change this if you want to expire all your assets\n    config.assets.version = '1.0'\n  end\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/boot.rb",
    "content": "require 'rubygems'\n\n# Set up gems listed in the Gemfile.\nENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)\n\nrequire 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/database.yml",
    "content": "# SQLite version 3.x\n#   gem install sqlite3\n#\n#   Ensure the SQLite 3 gem is defined in your Gemfile\n#   gem 'sqlite3'\ndevelopment:\n  adapter: sqlite3\n  database: db/development.sqlite3\n  pool: 5\n  timeout: 5000\n\n# Warning: The database defined as \"test\" will be erased and\n# re-generated from your development database when you run \"rake\".\n# Do not set this db to the same as development or production.\ntest:\n  adapter: sqlite3\n  database: db/test.sqlite3\n  pool: 5\n  timeout: 5000\n\nproduction:\n  adapter: sqlite3\n  database: db/production.sqlite3\n  pool: 5\n  timeout: 5000\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/environment.rb",
    "content": "# Load the rails application\nrequire File.expand_path('../application', __FILE__)\n\n# Initialize the rails application\nContacts::Application.initialize!\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/environments/development.rb",
    "content": "Contacts::Application.configure do\n  # Settings specified here will take precedence over those in config/application.rb\n\n  # In the development environment your application's code is reloaded on\n  # every request. This slows down response time but is perfect for development\n  # since you don't have to restart the web server when you make code changes.\n  config.cache_classes = false\n\n  # Log error messages when you accidentally call methods on nil.\n  config.whiny_nils = true\n\n  # Show full error reports and disable caching\n  config.consider_all_requests_local       = true\n  config.action_controller.perform_caching = false\n\n  # Don't care if the mailer can't send\n  config.action_mailer.raise_delivery_errors = false\n\n  # Print deprecation notices to the Rails logger\n  config.active_support.deprecation = :log\n\n  # Only use best-standards-support built into browsers\n  config.action_dispatch.best_standards_support = :builtin\n\n  # Raise exception on mass assignment protection for Active Record models\n  config.active_record.mass_assignment_sanitizer = :strict\n\n  # Log the query plan for queries taking more than this (works\n  # with SQLite, MySQL, and PostgreSQL)\n  config.active_record.auto_explain_threshold_in_seconds = 0.5\n\n  # Do not compress assets\n  config.assets.compress = false\n\n  # Expands the lines which load the assets\n  config.assets.debug = true\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/environments/production.rb",
    "content": "Contacts::Application.configure do\n  # Settings specified here will take precedence over those in config/application.rb\n\n  # Code is not reloaded between requests\n  config.cache_classes = true\n\n  # Full error reports are disabled and caching is turned on\n  config.consider_all_requests_local       = false\n  config.action_controller.perform_caching = true\n\n  # Disable Rails's static asset server (Apache or nginx will already do this)\n  config.serve_static_assets = false\n\n  # Compress JavaScripts and CSS\n  config.assets.compress = true\n\n  # Don't fallback to assets pipeline if a precompiled asset is missed\n  config.assets.compile = false\n\n  # Generate digests for assets URLs\n  config.assets.digest = true\n\n  # Defaults to nil and saved in location specified by config.assets.prefix\n  # config.assets.manifest = YOUR_PATH\n\n  # Specifies the header that your server uses for sending files\n  # config.action_dispatch.x_sendfile_header = \"X-Sendfile\" # for apache\n  # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx\n\n  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.\n  # config.force_ssl = true\n\n  # See everything in the log (default is :info)\n  # config.log_level = :debug\n\n  # Prepend all log lines with the following tags\n  # config.log_tags = [ :subdomain, :uuid ]\n\n  # Use a different logger for distributed setups\n  # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)\n\n  # Use a different cache store in production\n  # config.cache_store = :mem_cache_store\n\n  # Enable serving of images, stylesheets, and JavaScripts from an asset server\n  # config.action_controller.asset_host = \"http://assets.example.com\"\n\n  # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)\n  # config.assets.precompile += %w( search.js )\n\n  # Disable delivery errors, bad email addresses will be ignored\n  # config.action_mailer.raise_delivery_errors = false\n\n  # Enable threaded mode\n  # config.threadsafe!\n\n  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to\n  # the I18n.default_locale when a translation can not be found)\n  config.i18n.fallbacks = true\n\n  # Send deprecation notices to registered listeners\n  config.active_support.deprecation = :notify\n\n  # Log the query plan for queries taking more than this (works\n  # with SQLite, MySQL, and PostgreSQL)\n  # config.active_record.auto_explain_threshold_in_seconds = 0.5\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/environments/test.rb",
    "content": "Contacts::Application.configure do\n  # Settings specified here will take precedence over those in config/application.rb\n\n  # The test environment is used exclusively to run your application's\n  # test suite. You never need to work with it otherwise. Remember that\n  # your test database is \"scratch space\" for the test suite and is wiped\n  # and recreated between test runs. Don't rely on the data there!\n  config.cache_classes = true\n\n  # Configure static asset server for tests with Cache-Control for performance\n  config.serve_static_assets = true\n  config.static_cache_control = \"public, max-age=3600\"\n\n  # Log error messages when you accidentally call methods on nil\n  config.whiny_nils = true\n\n  # Show full error reports and disable caching\n  config.consider_all_requests_local       = true\n  config.action_controller.perform_caching = false\n\n  # Raise exceptions instead of rendering exception templates\n  config.action_dispatch.show_exceptions = false\n\n  # Disable request forgery protection in test environment\n  config.action_controller.allow_forgery_protection    = false\n\n  # Tell Action Mailer not to deliver emails to the real world.\n  # The :test delivery method accumulates sent emails in the\n  # ActionMailer::Base.deliveries array.\n  config.action_mailer.delivery_method = :test\n\n  # Raise exception on mass assignment protection for Active Record models\n  config.active_record.mass_assignment_sanitizer = :strict\n\n  # Print deprecation notices to the stderr\n  config.active_support.deprecation = :stderr\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/initializers/backtrace_silencers.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.\n# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }\n\n# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.\n# Rails.backtrace_cleaner.remove_silencers!\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/initializers/inflections.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# Add new inflection rules using the following format\n# (all these examples are active by default):\n# ActiveSupport::Inflector.inflections do |inflect|\n#   inflect.plural /^(ox)$/i, '\\1en'\n#   inflect.singular /^(ox)en/i, '\\1'\n#   inflect.irregular 'person', 'people'\n#   inflect.uncountable %w( fish sheep )\n# end\n#\n# These inflection rules are supported but not enabled by default:\n# ActiveSupport::Inflector.inflections do |inflect|\n#   inflect.acronym 'RESTful'\n# end\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/initializers/mime_types.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# Add new mime types for use in respond_to blocks:\n# Mime::Type.register \"text/richtext\", :rtf\n# Mime::Type.register_alias \"text/html\", :iphone\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/initializers/secret_token.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# Your secret key for verifying the integrity of signed cookies.\n# If you change this key, all old signed cookies will become invalid!\n# Make sure the secret is at least 30 characters and all random,\n# no regular words or you'll be exposed to dictionary attacks.\nContacts::Application.config.secret_token = '830798170fe06fbf75c3bdc4726f712bd5aeec8f460199afbabb88fd0a77a2077c0e8e5112d845d80d216e5c9d7a53e0cdb1ef5ea120008dc6c7d993f5c1389d'\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/initializers/session_store.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\nContacts::Application.config.session_store :cookie_store, key: '_contacts_session'\n\n# Use the database for sessions instead of the cookie-based default,\n# which shouldn't be used to store highly confidential information\n# (create the session table with \"rails generate session_migration\")\n# Contacts::Application.config.session_store :active_record_store\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/initializers/wrap_parameters.rb",
    "content": "# Be sure to restart your server when you modify this file.\n#\n# This file contains settings for ActionController::ParamsWrapper which\n# is enabled by default.\n\n# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.\nActiveSupport.on_load(:action_controller) do\n  wrap_parameters format: [:json]\nend\n\n# Disable root element in JSON by default.\nActiveSupport.on_load(:active_record) do\n  self.include_root_in_json = false\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/locales/en.yml",
    "content": "# Sample localization file for English. Add more files in this directory for other locales.\n# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.\n\nen:\n  hello: \"Hello world\"\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config/routes.rb",
    "content": "Contacts::Application.routes.draw do\n\n  root :to => \"layouts#index\"\n\n  scope \"api\" do\n    resources :contacts\n  end\n\n  match \"*path\" => \"layouts#index\"\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/config.ru",
    "content": "# This file is used by Rack-based servers to start the application.\n\nrequire ::File.expand_path('../config/environment',  __FILE__)\nrun Contacts::Application\n"
  },
  {
    "path": "chapter9/recipe1/contacts/db/migrate/20130221092802_create_contacts.rb",
    "content": "class CreateContacts < ActiveRecord::Migration\n  def change\n    create_table :contacts do |t|\n      t.string :firstname\n      t.string :lastname\n      t.integer :age\n\n      t.timestamps\n    end\n  end\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/db/schema.rb",
    "content": "# encoding: UTF-8\n# This file is auto-generated from the current state of the database. Instead\n# of editing this file, please use the migrations feature of Active Record to\n# incrementally modify your database, and then regenerate this schema definition.\n#\n# Note that this schema.rb definition is the authoritative source for your\n# database schema. If you need to create the application database on another\n# system, you should be using db:schema:load, not running all the migrations\n# from scratch. The latter is a flawed and unsustainable approach (the more migrations\n# you'll amass, the slower it'll run and the greater likelihood for issues).\n#\n# It's strongly recommended to check this file into your version control system.\n\nActiveRecord::Schema.define(:version => 20130221092802) do\n\n  create_table \"contacts\", :force => true do |t|\n    t.string   \"firstname\"\n    t.string   \"lastname\"\n    t.integer  \"age\"\n    t.datetime \"created_at\", :null => false\n    t.datetime \"updated_at\", :null => false\n  end\n\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/db/seeds.rb",
    "content": "# This file should contain all the record creation needed to seed the database with its default values.\n# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).\n#\n# Examples:\n#\n#   cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])\n#   Mayor.create(name: 'Emanuel', city: cities.first)\n"
  },
  {
    "path": "chapter9/recipe1/contacts/doc/README_FOR_APP",
    "content": "Use this README file to introduce your application and point to useful places in the API for learning more.\nRun \"rake doc:app\" to generate API documentation for your models, controllers, helpers, and libraries.\n"
  },
  {
    "path": "chapter9/recipe1/contacts/lib/assets/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/lib/tasks/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/public/404.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>The page you were looking for doesn't exist (404)</title>\n  <style type=\"text/css\">\n    body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }\n    div.dialog {\n      width: 25em;\n      padding: 0 4em;\n      margin: 4em auto 0 auto;\n      border: 1px solid #ccc;\n      border-right-color: #999;\n      border-bottom-color: #999;\n    }\n    h1 { font-size: 100%; color: #f00; line-height: 1.5em; }\n  </style>\n</head>\n\n<body>\n  <!-- This file lives in public/404.html -->\n  <div class=\"dialog\">\n    <h1>The page you were looking for doesn't exist.</h1>\n    <p>You may have mistyped the address or the page may have moved.</p>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "chapter9/recipe1/contacts/public/422.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>The change you wanted was rejected (422)</title>\n  <style type=\"text/css\">\n    body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }\n    div.dialog {\n      width: 25em;\n      padding: 0 4em;\n      margin: 4em auto 0 auto;\n      border: 1px solid #ccc;\n      border-right-color: #999;\n      border-bottom-color: #999;\n    }\n    h1 { font-size: 100%; color: #f00; line-height: 1.5em; }\n  </style>\n</head>\n\n<body>\n  <!-- This file lives in public/422.html -->\n  <div class=\"dialog\">\n    <h1>The change you wanted was rejected.</h1>\n    <p>Maybe you tried to change something you didn't have access to.</p>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "chapter9/recipe1/contacts/public/500.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>We're sorry, but something went wrong (500)</title>\n  <style type=\"text/css\">\n    body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }\n    div.dialog {\n      width: 25em;\n      padding: 0 4em;\n      margin: 4em auto 0 auto;\n      border: 1px solid #ccc;\n      border-right-color: #999;\n      border-bottom-color: #999;\n    }\n    h1 { font-size: 100%; color: #f00; line-height: 1.5em; }\n  </style>\n</head>\n\n<body>\n  <!-- This file lives in public/500.html -->\n  <div class=\"dialog\">\n    <h1>We're sorry, but something went wrong.</h1>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "chapter9/recipe1/contacts/public/robots.txt",
    "content": "# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file\n#\n# To ban all spiders from the entire site uncomment the next two lines:\n# User-Agent: *\n# Disallow: /\n"
  },
  {
    "path": "chapter9/recipe1/contacts/script/rails",
    "content": "#!/usr/bin/env ruby\n# This command will automatically be run when you run \"rails\" with Rails 3 gems installed from the root of your application.\n\nAPP_PATH = File.expand_path('../../config/application',  __FILE__)\nrequire File.expand_path('../../config/boot',  __FILE__)\nrequire 'rails/commands'\n"
  },
  {
    "path": "chapter9/recipe1/contacts/spec/javascripts/angular/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/test/fixtures/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/test/fixtures/contacts.yml",
    "content": "# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html\n\none:\n  firstname: MyString\n  lastname: MyString\n  age: 1\n\ntwo:\n  firstname: MyString\n  lastname: MyString\n  age: 1\n"
  },
  {
    "path": "chapter9/recipe1/contacts/test/functional/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/test/functional/contacts_controller_test.rb",
    "content": "require 'test_helper'\n\nclass ContactsControllerTest < ActionController::TestCase\n  setup do\n    @contact = contacts(:one)\n  end\n\n  test \"should get index\" do\n    get :index\n    assert_response :success\n    assert_not_nil assigns(:contacts)\n  end\n\n  test \"should get new\" do\n    get :new\n    assert_response :success\n  end\n\n  test \"should create contact\" do\n    assert_difference('Contact.count') do\n      post :create, contact: { age: @contact.age, firstname: @contact.firstname, lastname: @contact.lastname }\n    end\n\n    assert_redirected_to contact_path(assigns(:contact))\n  end\n\n  test \"should show contact\" do\n    get :show, id: @contact\n    assert_response :success\n  end\n\n  test \"should get edit\" do\n    get :edit, id: @contact\n    assert_response :success\n  end\n\n  test \"should update contact\" do\n    put :update, id: @contact, contact: { age: @contact.age, firstname: @contact.firstname, lastname: @contact.lastname }\n    assert_redirected_to contact_path(assigns(:contact))\n  end\n\n  test \"should destroy contact\" do\n    assert_difference('Contact.count', -1) do\n      delete :destroy, id: @contact\n    end\n\n    assert_redirected_to contacts_path\n  end\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/test/integration/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/test/performance/browsing_test.rb",
    "content": "require 'test_helper'\nrequire 'rails/performance_test_help'\n\nclass BrowsingTest < ActionDispatch::PerformanceTest\n  # Refer to the documentation for all available options\n  # self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory]\n  #                          :output => 'tmp/performance', :formats => [:flat] }\n\n  def test_homepage\n    get '/'\n  end\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/test/test_helper.rb",
    "content": "ENV[\"RAILS_ENV\"] = \"test\"\nrequire File.expand_path('../../config/environment', __FILE__)\nrequire 'rails/test_help'\n\nclass ActiveSupport::TestCase\n  # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.\n  #\n  # Note: You'll currently still have to declare fixtures explicitly in integration tests\n  # -- they do not yet inherit this setting\n  fixtures :all\n\n  # Add more helper methods to be used by all tests here...\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/test/unit/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/test/unit/contact_test.rb",
    "content": "require 'test_helper'\n\nclass ContactTest < ActiveSupport::TestCase\n  # test \"the truth\" do\n  #   assert true\n  # end\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/test/unit/helpers/contacts_helper_test.rb",
    "content": "require 'test_helper'\n\nclass ContactsHelperTest < ActionView::TestCase\nend\n"
  },
  {
    "path": "chapter9/recipe1/contacts/vendor/assets/javascripts/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/vendor/assets/javascripts/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.0.5\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * @param {string} url A parameterized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g.\n *   `http://example.com:8080/api`), you'll need to escape the colon character before the port\n *   number, like this: `$resource('http://example.com\\\\:8080/api')`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods.\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the following format:\n *\n *       {action1: {method:?, params:?, isArray:?},\n *        action2: {method:?, params:?, isArray:?},\n *        ...}\n *\n *   Where:\n *\n *   - `action` â€“ {string} â€“ The name of action. This name becomes the name of the method on your\n *     resource object.\n *   - `method` â€“ {string} â€“ HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,\n *     and `JSONP`\n *   - `params` â€“ {object=} â€“ Optional set of pre-bound parameters for this action.\n *   - isArray â€“ {boolean=} â€“ If true then the returned object for this action is an array, see\n *     `returns` section.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class. The actions `save`, `remove` and `delete` are available on it\n *   as  methods with the `$` prefix. This allows you to easily perform CRUD operations (create,\n *   read, update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most case one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'01234', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n * It's worth noting that the success callback for `get`, `query` and other method gets passed\n * in the response that came from the server as well as $http header getter function, so one\n * could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Buzz client\n\n   Let's look at what a buzz client created with the `$resource` service looks like:\n    <doc:example>\n      <doc:source jsfiddle=\"false\">\n       <script>\n         function BuzzController($resource) {\n           this.userId = 'googlebuzz';\n           this.Activity = $resource(\n             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',\n             {alt:'json', callback:'JSON_CALLBACK'},\n             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}\n           );\n         }\n\n         BuzzController.prototype = {\n           fetch: function() {\n             this.activities = this.Activity.get({userId:this.userId});\n           },\n           expandReplies: function(activity) {\n             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});\n           }\n         };\n         BuzzController.$inject = ['$resource'];\n       </script>\n\n       <div ng-controller=\"BuzzController\">\n         <input ng-model=\"userId\"/>\n         <button ng-click=\"fetch()\">fetch</button>\n         <hr/>\n         <div ng-repeat=\"item in activities.data.items\">\n           <h1 style=\"font-size: 15px;\">\n             <img src=\"{{item.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{item.actor.profileUrl}}\">{{item.actor.name}}</a>\n             <a href ng-click=\"expandReplies(item)\" style=\"float: right;\">Expand replies: {{item.links.replies[0].count}}</a>\n           </h1>\n           {{item.object.content | html}}\n           <div ng-repeat=\"reply in item.replies.data.items\" style=\"margin-left: 20px;\">\n             <img src=\"{{reply.actor.thumbnailUrl}}\" style=\"max-height:30px;max-width:30px;\"/>\n             <a href=\"{{reply.actor.profileUrl}}\">{{reply.actor.name}}</a>: {{reply.content | html}}\n           </div>\n         </div>\n       </div>\n      </doc:source>\n      <doc:scenario>\n      </doc:scenario>\n    </doc:example>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$parse', function($http, $parse) {\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction,\n        getter = function(obj, path) {\n          return $parse(path)(obj);\n        };\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n     * encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace((pctEncodeSpaces ? null : /%20/g), '+');\n    }\n\n    function Route(template, defaults) {\n      this.template = template = template + '#';\n      this.defaults = defaults || {};\n      var urlParams = this.urlParams = {};\n      forEach(template.split(/\\W/), function(param){\n        if (param && (new RegExp(\"(^|[^\\\\\\\\]):\" + param + \"\\\\W\").test(template))) {\n          urlParams[param] = true;\n        }\n      });\n      this.template = template.replace(/\\\\:/g, ':');\n    }\n\n    Route.prototype = {\n      url: function(params) {\n        var self = this,\n            url = this.template,\n            val,\n            encodedVal;\n\n        params = params || {};\n        forEach(this.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W)\", \"g\"), encodedVal + \"$1\");\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n        url = url.replace(/\\/?#$/, '');\n        var query = [];\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));\n          }\n        });\n        query.sort();\n        url = url.replace(/\\/*$/, '');\n        return url + (query.length ? '?' + query.join('&') : '');\n      }\n    };\n\n\n    function ResourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function Resource(value){\n        copy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        action.method = angular.uppercase(action.method);\n        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {};\n          var data;\n          var success = noop;\n          var error = null;\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw \"Expected between 0-4 arguments [params, data, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n\n          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));\n          $http({\n            method: action.method,\n            url: route.url(extend({}, extractParams(data, action.params || {}), params)),\n            data: data\n          }).then(function(response) {\n              var data = response.data;\n\n              if (data) {\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    value.push(new Resource(item));\n                  });\n                } else {\n                  copy(data, value);\n                }\n              }\n              (success||noop)(value, response.headers);\n            }, error);\n\n          return value;\n        };\n\n\n        Resource.prototype['$' + name] = function(a1, a2, a3) {\n          var params = extractParams(this),\n              success = noop,\n              error;\n\n          switch(arguments.length) {\n          case 3: params = a1; success = a2; error = a3; break;\n          case 2:\n          case 1:\n            if (isFunction(a1)) {\n              success = a1;\n              error = a2;\n            } else {\n              params = a1;\n              success = a2 || noop;\n            }\n          case 0: break;\n          default:\n            throw \"Expected between 1-3 arguments [params, success, error], got \" +\n              arguments.length + \" arguments.\";\n          }\n          var data = hasBody ? this : undefined;\n          Resource[name].call(this, params, data, success, error);\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return ResourceFactory;\n  }]);\n\n})(window, window.angular);"
  },
  {
    "path": "chapter9/recipe1/contacts/vendor/assets/javascripts/angular.js",
    "content": "/**\n * @license AngularJS v1.0.5\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n////////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\n\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\nfunction fromCharCode(code) {return String.fromCharCode(code);}\n\n\nvar /** holds major version number for IE or NaN for real browsers */\n    msie              = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * Note: this function was previously known as `angular.foreach`.\n *\n   <pre>\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key){\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender:male']);\n   </pre>\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\n\n\n/**\n * @private\n * @param {*} obj\n * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...)\n */\nfunction isArrayLike(obj) {\n  if (!obj || (typeof obj.length !== 'number')) return false;\n\n  // We have on object which has length property. Should we treat it as array?\n  if (typeof obj.hasOwnProperty != 'function' &&\n      typeof obj.constructor != 'function') {\n    // This is here for IE8: it is a bogus object treat it as array;\n    return true;\n  } else  {\n    return obj instanceof JQLite ||                      // JQLite\n           (jQuery && obj instanceof jQuery) ||          // jQuery\n           toString.call(obj) !== '[object Object]' ||   // some browser native object\n           typeof obj.callee === 'function';              // arguments (on IE8 looks like regular obj)\n  }\n}\n\n\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)){\n      for (key in obj) {\n        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n      obj.forEach(iterator, context);\n    } else if (isArrayLike(obj)) {\n      for (key = 0; key < obj.length; key++)\n        iterator.call(context, obj[key], key);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value) };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @function\n *\n * @description\n * Extends the destination object `dst` by copying all of the properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n */\nfunction extend(dst) {\n  forEach(arguments, function(obj){\n    if (obj !== dst) {\n      forEach(obj, function(value, key){\n        dst[key] = value;\n      });\n    }\n  });\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   <pre>\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   </pre>\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   <pre>\n     function transformer(transformationFn, value) {\n       return (transformationFn || identity)(value);\n     };\n   </pre>\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value == 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value != 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value == 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value == 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value == 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value){\n  return toString.apply(value) == '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(value) {\n  return toString.apply(value) == '[object Array]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value == 'function';}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.apply(obj) === '[object File]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value == 'boolean';\n}\n\n\nfunction trim(value) {\n  return isString(value) ? value.replace(/^\\s*/, '').replace(/\\s*$/, '') : value;\n}\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return node &&\n    (node.nodeName  // we are a direct element\n    || (node.bind && node.find));  // we have a bind and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str){\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var size = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)){\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        size++;\n  }\n\n  return size;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for ( var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If  `source` is not an object or array, `source` is returned.\n *\n * Note: this function is used to augment the Object type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n */\nfunction copy(source, destination){\n  if (isWindow(source) || isScope(source)) throw Error(\"Can't copy Window or Scope\");\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, []);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isObject(source)) {\n        destination = copy(source, {});\n      }\n    }\n  } else {\n    if (source === destination) throw Error(\"Can't copy equivalent objects or arrays\");\n    if (isArray(source)) {\n      destination.length = 0;\n      for ( var i = 0; i < source.length; i++) {\n        destination.push(copy(source[i]));\n      }\n    } else {\n      forEach(destination, function(value, key){\n        delete destination[key];\n      });\n      for ( var key in source) {\n        destination[key] = copy(source[key]);\n      }\n    }\n  }\n  return destination;\n}\n\n/**\n * Create a shallow copy of an object\n */\nfunction shallowCopy(src, dst) {\n  dst = dst || {};\n\n  for(var key in src) {\n    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, arrays and\n * objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties pass `===` comparison.\n * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)\n *\n * During a property comparision, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only be identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        return isDate(o2) && o1.getTime() == o2.getTime();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet[key] &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also\n * known as [function currying](http://en.wikipedia.org/wiki/Currying).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (/^\\$+/.test(key)) {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @function\n *\n * @description\n * Serializes input into a JSON-formatted string.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string} Jsonified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|Date|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.html('');\n  } catch(e) {}\n  // As Per DOM Standards\n  var TEXT_NODE = 3;\n  var elemHtml = jqLite('<div>').append(element).html();\n  try {\n    return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :\n        elemHtml.\n          match(/^(<[^>]+>)/)[1].\n          replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n  } catch(e) {\n    return lowercase(elemHtml);\n  }\n\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns Object.<(string|boolean)>\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue){\n    if (keyValue) {\n      key_value = keyValue.split('=');\n      key = decodeURIComponent(key_value[0]);\n      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too agressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace((pctEncodeSpaces ? null : /%20/g), '+');\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngApp\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to auto-bootstrap on application. Only\n * one directive can be used per HTML document. The directive\n * designates the root of the application and is typically placed\n * at the root of the page.\n *\n * In the example below if the `ngApp` directive would not be placed\n * on the `html` element then the document would not be compiled\n * and the `{{ 1+2 }}` would not be resolved to `3`.\n *\n * `ngApp` is the easiest way to bootstrap an application.\n *\n <doc:example>\n   <doc:source>\n    I can add: 1 + 2 =  {{ 1+2 }}\n   </doc:source>\n </doc:example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * @param {Element} element DOM element which is the root of angular application.\n * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}\n * @returns {AUTO.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  element = jqLite(element);\n  modules = modules || [];\n  modules.unshift(['$provide', function($provide) {\n    $provide.value('$rootElement', element);\n  }]);\n  modules.unshift('ng');\n  var injector = createInjector(modules);\n  injector.invoke(\n    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){\n      scope.$apply(function() {\n        element.data('$injector', injector);\n        compile(element)(scope);\n      });\n    }]\n  );\n  return injector;\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator){\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // reset to jQuery or default to us.\n  if (jQuery) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    JQLitePatchJQueryRemove('remove', true);\n    JQLitePatchJQueryRemove('empty');\n    JQLitePatchJQueryRemove('html');\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error of the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw new Error(\"Argument '\" + (name || '?') + \"' is \" + (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * @ngdoc interface\n * @name angular.Module\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  return ensure(ensure(window, 'angular', Object), 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @description\n     *\n     * The `angular.module` is a global place for creating and registering Angular modules. All\n     * modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     *\n     * # Module\n     *\n     * A module is a collocation of services, directives, filters, and configuration information. Module\n     * is used to configure the {@link AUTO.$injector $injector}.\n     *\n     * <pre>\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * });\n     * </pre>\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * <pre>\n     * var injector = angular.injector(['ng', 'MyModule'])\n     * </pre>\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the\n     *        the module is being retrieved for further configuration.\n     * @param {Function} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw Error('No module: ' + name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @propertyOf angular.Module\n           * @returns {Array.<string>} List of module names which must be loaded before this module.\n           * @description\n           * Holds the list of modules which the injector will load before the current module is loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @propertyOf angular.Module\n           * @returns {string} Name of the module.\n           * @description\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link AUTO.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link AUTO.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @methodOf angular.Module\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link AUTO.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @methodOf angular.Module\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link AUTO.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @methodOf angular.Module\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @methodOf angular.Module\n           * @param {string} name Controller name.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @methodOf angular.Module\n           * @param {string} name directive name\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @methodOf angular.Module\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @methodOf angular.Module\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          }\n        }\n      });\n    };\n  });\n\n}\n\n/**\n * @ngdoc property\n * @name angular.version\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.0.5',    // all of these placeholder strings will be replaced by rake's\n  major: 1,    // compile task\n  minor: 0,\n  dot: 5,\n  codeName: 'flatulent-propulsion'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop':noop,\n    'bind':bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity':identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0}\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCsp: ngCspDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngSubmit: ngSubmitDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngView: ngViewDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $route: $RouteProvider,\n        $routeParams: $RouteParamsProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider\n      });\n    }\n  ]);\n}\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if\n * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite\n * implementation (commonly referred to as jqLite).\n *\n * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`\n * event fired.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality\n * within a very small footprint, so only a subset of the jQuery API - methods, arguments and\n * invocation styles - are supported.\n *\n * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never\n * raw DOM references.\n *\n * ## Angular's jQuery lite provides the following methods:\n *\n * - [addClass()](http://api.jquery.com/addClass/)\n * - [after()](http://api.jquery.com/after/)\n * - [append()](http://api.jquery.com/append/)\n * - [attr()](http://api.jquery.com/attr/)\n * - [bind()](http://api.jquery.com/bind/)\n * - [children()](http://api.jquery.com/children/)\n * - [clone()](http://api.jquery.com/clone/)\n * - [contents()](http://api.jquery.com/contents/)\n * - [css()](http://api.jquery.com/css/)\n * - [data()](http://api.jquery.com/data/)\n * - [eq()](http://api.jquery.com/eq/)\n * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.\n * - [hasClass()](http://api.jquery.com/hasClass/)\n * - [html()](http://api.jquery.com/html/)\n * - [next()](http://api.jquery.com/next/)\n * - [parent()](http://api.jquery.com/parent/)\n * - [prepend()](http://api.jquery.com/prepend/)\n * - [prop()](http://api.jquery.com/prop/)\n * - [ready()](http://api.jquery.com/ready/)\n * - [remove()](http://api.jquery.com/remove/)\n * - [removeAttr()](http://api.jquery.com/removeAttr/)\n * - [removeClass()](http://api.jquery.com/removeClass/)\n * - [removeData()](http://api.jquery.com/removeData/)\n * - [replaceWith()](http://api.jquery.com/replaceWith/)\n * - [text()](http://api.jquery.com/text/)\n * - [toggleClass()](http://api.jquery.com/toggleClass/)\n * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.\n * - [unbind()](http://api.jquery.com/unbind/)\n * - [val()](http://api.jquery.com/val/)\n * - [wrap()](http://api.jquery.com/wrap/)\n *\n * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:\n *\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nvar jqCache = JQLite.cache = {},\n    jqName = JQLite.expando = 'ng-' + new Date().getTime(),\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction JQLitePatchJQueryRemove(name, dispatchThis) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch() {\n    var list = [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children,\n        fns, events;\n\n    while(list.length) {\n      set = list.shift();\n      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n        element = jqLite(set[setIndex]);\n        if (fireEvent) {\n          element.triggerHandler('$destroy');\n        } else {\n          fireEvent = !fireEvent;\n        }\n        for(childIndex = 0, childLength = (children = element.children()).length;\n            childIndex < childLength;\n            childIndex++) {\n          list.push(jQuery(children[childIndex]));\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw Error('selectors not implemented');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    var div = document.createElement('div');\n    // Read about the NoScope elements here:\n    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx\n    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!\n    div.removeChild(div.firstChild); // remove the superfluous div\n    JQLiteAddNodes(this, div.childNodes);\n    this.remove(); // detach the elements from the temporary DOM div.\n  } else {\n    JQLiteAddNodes(this, element);\n  }\n}\n\nfunction JQLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction JQLiteDealoc(element){\n  JQLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    JQLiteDealoc(children[i]);\n  }\n}\n\nfunction JQLiteUnbind(element, type, fn) {\n  var events = JQLiteExpandoStore(element, 'events'),\n      handle = JQLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    if (isUndefined(fn)) {\n      removeEventListenerFn(element, type, events[type]);\n      delete events[type];\n    } else {\n      arrayRemove(events[type], fn);\n    }\n  }\n}\n\nfunction JQLiteRemoveData(element) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      JQLiteUnbind(element);\n    }\n    delete jqCache[expandoId];\n    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.\n  }\n}\n\nfunction JQLiteExpandoStore(element, key, value) {\n  var expandoId = element[jqName],\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element[jqName] = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction JQLiteData(element, key, value) {\n  var data = JQLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    JQLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction JQLiteHasClass(element, selector) {\n  return ((\" \" + element.className + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction JQLiteRemoveClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.className = trim(\n          (\" \" + element.className + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \")\n      );\n    });\n  }\n}\n\nfunction JQLiteAddClass(element, cssClasses) {\n  if (cssClasses) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      if (!JQLiteHasClass(element, cssClass)) {\n        element.className = trim(element.className + ' ' + trim(cssClass));\n      }\n    });\n  }\n}\n\nfunction JQLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction JQLiteController(element, name) {\n  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction JQLiteInheritedData(element, name, value) {\n  element = jqLite(element);\n\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element[0].nodeType == 9) {\n    element = element.find('html');\n  }\n\n  while (element.length) {\n    if (value = element.data(name)) return value;\n    element = element.parent();\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9\n    // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n    JQLite(window).bind('load', trigger); // fallback to window.onload for others\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: JQLiteData,\n  inheritedData: JQLiteInheritedData,\n\n  scope: function(element) {\n    return JQLiteInheritedData(element, '$scope');\n  },\n\n  controller: JQLiteController ,\n\n  injector: function(element) {\n    return JQLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: JQLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: extend((msie < 9)\n      ? function(element, value) {\n        if (element.nodeType == 1 /** Element */) {\n          if (isUndefined(value))\n            return element.innerText;\n          element.innerText = value;\n        } else {\n          if (isUndefined(value))\n            return element.nodeValue;\n          element.nodeValue = value;\n        }\n      }\n      : function(element, value) {\n        if (isUndefined(value)) {\n          return element.textContent;\n        }\n        element.textContent = value;\n      }, {$dv:''}),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      JQLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  }\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n\n    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for(i=0; i < this.length; i++) {\n          if (fn === JQLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        if (this.length)\n          return fn(this[0], arg1, arg2);\n      }\n    } else {\n      // we are a write, so apply to all children\n      for(i=0; i < this.length; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n    return fn.$dv;\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    forEach(events[type || event.type], function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: JQLiteRemoveData,\n\n  dealoc: JQLiteDealoc,\n\n  bind: function bindFn(element, type, fn){\n    var events = JQLiteExpandoStore(element, 'events'),\n        handle = JQLiteExpandoStore(element, 'handle');\n\n    if (!events) JQLiteExpandoStore(element, 'events', events = {});\n    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var counter = 0;\n\n          events.mouseenter = [];\n          events.mouseleave = [];\n\n          bindFn(element, 'mouseover', function(event) {\n            counter++;\n            if (counter == 1) {\n              handle(event, 'mouseenter');\n            }\n          });\n          bindFn(element, 'mouseout', function(event) {\n            counter --;\n            if (counter == 0) {\n              handle(event, 'mouseleave');\n            }\n          });\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type]\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  unbind: JQLiteUnbind,\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    JQLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1)\n        element.appendChild(child);\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        if (index) {\n          element.insertBefore(child, index);\n        } else {\n          element.appendChild(child);\n          index = child;\n        }\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    JQLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: JQLiteAddClass,\n  removeClass: JQLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (isUndefined(condition)) {\n      condition = !JQLiteHasClass(element, selector);\n    }\n    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    return element.getElementsByTagName(selector);\n  },\n\n  clone: JQLiteClone,\n\n  triggerHandler: function(element, eventName) {\n    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];\n\n    forEach(eventFns, function(fn) {\n      fn.call(element, null);\n    });\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (value == undefined) {\n        value = fn(this[i], arg1, arg2);\n        if (value !== undefined) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        JQLiteAddNodes(value, fn(this[i], arg1, arg2));\n      }\n    }\n    return value == undefined ? this : value;\n  };\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'object' && obj !== null) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = nextUid();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array){\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * A map where multiple values can be added to the same key such that they form a queue.\n * @returns {HashQueueMap}\n */\nfunction HashQueueMap() {}\nHashQueueMap.prototype = {\n  /**\n   * Same as array push, but using an array as the value for the hash\n   */\n  push: function(key, value) {\n    var array = this[key = hashKey(key)];\n    if (!array) {\n      this[key] = [value];\n    } else {\n      array.push(value);\n    }\n  },\n\n  /**\n   * Same as array shift, but using an array as the value for the hash\n   */\n  shift: function(key) {\n    var array = this[key = hashKey(key)];\n    if (array) {\n      if (array.length == 1) {\n        delete this[key];\n        return array[0];\n      } else {\n        return array.shift();\n      }\n    }\n  },\n\n  /**\n   * return the first item without deleting it\n   */\n  peek: function(key) {\n    var array = this[hashKey(key)];\n    if (array) {\n    return array[0];\n    }\n  }\n};\n\n/**\n * @ngdoc function\n * @name angular.injector\n * @function\n *\n * @description\n * Creates an injector function that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.\n *\n * @example\n * Typical usage\n * <pre>\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * </pre>\n */\n\n\n/**\n * @ngdoc overview\n * @name AUTO\n * @description\n *\n * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn == 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      fnText = fn.toString().replace(STRIP_COMMENTS, '');\n      argDecl = fnText.match(FN_ARGS);\n      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n        arg.replace(FN_ARG, function(all, underscore, name){\n          $inject.push(name);\n        });\n      });\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn')\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc object\n * @name AUTO.$injector\n * @function\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link AUTO.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * <pre>\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   }).toBe($injector);\n * </pre>\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following ways are all valid way of annotating function with injection arguments and are equivalent.\n *\n * <pre>\n *   // inferred (only works if code not minified/obfuscated)\n *   $inject.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $inject.invoke(explicit);\n *\n *   // inline\n *   $inject.invoke(['serviceA', function(serviceA){}]);\n * </pre>\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be\n * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation\n * tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding a `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#get\n * @methodOf AUTO.$injector\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#invoke\n * @methodOf AUTO.$injector\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!function} fn The function to invoke. The function arguments come form the function annotation.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#instantiate\n * @methodOf AUTO.$injector\n * @description\n * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies\n * all of the arguments to the constructor function as specified by the constructor annotation.\n *\n * @param {function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before\n *   the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$injector#annotate\n * @methodOf AUTO.$injector\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is used by the injector\n * to determine which services need to be injected into the function when the function is invoked. There are three\n * ways in which the function can be annotated with the needed dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting\n * the function into a string using `toString()` method and extracting the argument names.\n * <pre>\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies\n * are supported.\n *\n * # The `$inject` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of\n * services to be injected into the function.\n * <pre>\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController.$inject = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * </pre>\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very\n * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives\n * minification is a better choice:\n *\n * <pre>\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tempFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * </pre>\n *\n * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described\n *   above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc object\n * @name AUTO.$provide\n *\n * @description\n *\n * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.\n * The providers share the same name as the instance they create with the `Provider` suffixed to them.\n *\n * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of\n * a service. The Provider can have additional methods which would allow for configuration of the provider.\n *\n * <pre>\n *   function GreetProvider() {\n *     var salutation = 'Hello';\n *\n *     this.salutation = function(text) {\n *       salutation = text;\n *     };\n *\n *     this.$get = function() {\n *       return function (name) {\n *         return salutation + ' ' + name + '!';\n *       };\n *     };\n *   }\n *\n *   describe('Greeter', function(){\n *\n *     beforeEach(module(function($provide) {\n *       $provide.provider('greet', GreetProvider);\n *     });\n *\n *     it('should greet', inject(function(greet) {\n *       expect(greet('angular')).toEqual('Hello angular!');\n *     }));\n *\n *     it('should allow configuration of salutation', function() {\n *       module(function(greetProvider) {\n *         greetProvider.salutation('Ahoj');\n *       });\n *       inject(function(greet) {\n *         expect(greet('angular')).toEqual('Ahoj angular!');\n *       });\n *     )};\n *\n *   });\n * </pre>\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#provider\n * @methodOf AUTO.$provide\n * @description\n *\n * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n */\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#factory\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if only `$get` method is required.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for\n * `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#service\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for registering service of given class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#value\n * @methodOf AUTO.$provide\n * @description\n *\n * A short hand for configuring services if the `$get` method is a constant.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#constant\n * @methodOf AUTO.$provide\n * @description\n *\n * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected\n * into configuration function (other modules) and it is not interceptable by\n * {@link AUTO.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n */\n\n\n/**\n * @ngdoc method\n * @name AUTO.$provide#decorator\n * @methodOf AUTO.$provide\n * @description\n *\n * Decoration of service, allows the decorator to intercept the service instance creation. The\n * returned instance may be the original instance, or a new instance which delegates to the\n * original instance.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instanciated. The function is called using the {@link AUTO.$injector#invoke\n *    injector.invoke} method and is therefore fully injectable. Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = createInternalInjector(providerCache, function() {\n        throw Error(\"Unknown provider: \" + path.join(' <- '));\n      }),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    }\n  }\n\n  function provider(name, provider_) {\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw Error('Provider ' + name + ' must define $get factory method.');\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, value) { return factory(name, valueFn(value)); }\n\n  function constant(name, value) {\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [];\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n      if (isString(module)) {\n        var moduleFn = angularModule(module);\n        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n        try {\n          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = invokeArgs[0] == '$injector'\n                    ? providerInjector\n                    : providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isFunction(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + module;\n          throw e;\n        }\n      } else if (isArray(module)) {\n        try {\n          runBlocks.push(providerInjector.invoke(module));\n        } catch (e) {\n          if (e.message) e.message += ' from ' + String(module[module.length - 1]);\n          throw e;\n        }\n      } else {\n        assertArgFn(module, 'module');\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (typeof serviceName !== 'string') {\n        throw Error('Service name expected');\n      }\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw Error('Circular dependency: ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (!fn.$inject) {\n        // this means that we must be an array.\n        fn = fn[length];\n      }\n\n\n      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke\n      switch (self ? -1 : args.length) {\n        case  0: return fn();\n        case  1: return fn(args[0]);\n        case  2: return fn(args[0], args[1]);\n        case  3: return fn(args[0], args[1], args[2]);\n        case  4: return fn(args[0], args[1], args[2], args[3]);\n        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);\n        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);\n        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);\n        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);\n        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);\n        default: return fn.apply(self, args);\n      }\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate\n    };\n  }\n}\n/**\n * @ngdoc function\n * @name ng.$anchorScroll\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scroll to related element,\n * according to rules specified in\n * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.\n *\n * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ng.$browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name ng.$browser#addPollFn\n   * @methodOf ng.$browser\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base');\n\n  /**\n   * @name ng.$browser#url\n   * @methodOf ng.$browser\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      lastBrowserUrl = url;\n      if ($sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (replace) location.replace(url);\n        else location.href = url;\n      }\n      return self;\n    // getter\n    } else {\n      // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name ng.$browser#onUrlChange\n   * @methodOf ng.$browser\n   * @TODO(vojta): refactor to use node's syntax for events\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed by outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string=}\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^https?\\:\\/\\/[^\\/]*/, '') : '';\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name ng.$browser#cookies\n   * @methodOf ng.$browser\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cokkie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   * <ul>\n   *   <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>\n   *   <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>\n   *   <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>\n   * </ul>\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath + \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name ng.$browser#defer\n   * @methodOf ng.$browser\n   * @param {function()} fn A function, who's execution should be defered.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchroniously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name ng.$browser#defer.cancel\n   * @methodOf ng.$browser.defer\n   *\n   * @description\n   * Cancels a defered task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n/**\n * @ngdoc object\n * @name ng.$cacheFactory\n *\n * @description\n * Factory that constructs cache objects.\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw Error('cacheId ' + cacheId + ' taken');\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      return caches[cacheId] = {\n\n        put: function(key, value) {\n          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n          refresh(lruEntry);\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n        },\n\n\n        get: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          refresh(lruEntry);\n\n          return data[key];\n        },\n\n\n        remove: function(key) {\n          var lruEntry = lruHash[key];\n\n          if (!lruEntry) return;\n\n          if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n          if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n          link(lruEntry.n,lruEntry.p);\n\n          delete lruHash[key];\n          delete data[key];\n          size--;\n        },\n\n\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$templateCache\n *\n * @description\n * Cache used for storing html templates.\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\nvar NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';\n\n\n/**\n * @ngdoc function\n * @name ng.$compile\n * @function\n *\n * @description\n * Compiles a piece of HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope scope} and the template together.\n *\n * The compilation is a process of walking the DOM tree and trying to match DOM elements to\n * {@link ng.$compileProvider#directive directives}. For each match it\n * executes corresponding template function and collects the\n * instance functions into a single template function which is then returned.\n *\n * The template function can then be used once to produce the view or as it is the case with\n * {@link ng.directive:ngRepeat repeater} many-times, in which\n * case each call results in a view that is a DOM clone of the original template.\n *\n <doc:example module=\"compile\">\n   <doc:source>\n    <script>\n      // declare a new module, and inject the $compileProvider\n      angular.module('compile', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        })\n      });\n\n      function Ctrl($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }\n    </script>\n    <div ng-controller=\"Ctrl\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </doc:source>\n   <doc:scenario>\n     it('should auto compile', function() {\n       expect(element('div[compile]').text()).toBe('Hello Angular');\n       input('html').enter('{{name}}!');\n       expect(element('div[compile]').text()).toBe('Angular!');\n     });\n   </doc:scenario>\n </doc:example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower then given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *               `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *               cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *               called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original element\n * passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   <pre>\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   </pre>\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   <pre>\n *     var templateHTML = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clone`\n *   </pre>\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\n\n/**\n * @ngdoc service\n * @name ng.$compileProvider\n * @function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide'];\nfunction $CompileProvider($provide) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w\\-_]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w\\-_]+)(?:\\:([^;]+))?;?)/,\n      MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ',\n      urlSanitizationWhitelist = /^\\s*(https?|ftp|mailto):/;\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#directive\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Register a new directives with the compiler.\n   *\n   * @param {string} name Name of the directive in camel-case. (ie <code>ngBind</code> which will match as\n   *                <code>ng-bind</code>).\n   * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more\n   *                info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directive');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$compileProvider#urlSanitizationWhitelist\n   * @methodOf ng.$compileProvider\n   * @function\n   *\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during a[href] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into an\n   * absolute url. Afterwards the url is matched against the `urlSanitizationWhitelist` regular\n   * expression. If a match is found the original url is written into the dom. Otherwise the\n   * absolute url is prefixed with `'unsafe:'` string and only then it is written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.urlSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      urlSanitizationWhitelist = regexp;\n      return this;\n    }\n    return urlSanitizationWhitelist;\n  };\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope', '$document',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope,   $document) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      $normalize: directiveNormalize,\n\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            $$observers = this.$$observers,\n            normalizedVal;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n\n        // sanitize a[href] values\n        if (nodeName_(this.$$element[0]) === 'A' && key === 'href') {\n          urlSanitizationNode.setAttribute('href', value);\n\n          // href property always returns normalized absolute url, so we can match against that\n          normalizedVal = urlSanitizationNode.href;\n          if (!normalizedVal.match(urlSanitizationWhitelist)) {\n            this[key] = value = 'unsafe:' + normalizedVal;\n          }\n        }\n\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * Observe an interpolated attribute.\n       * The observer will never be called, if given attribute is not interpolated.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(*)} fn Function that will be called whenever the attribute value changes.\n       * @returns {function(*)} the `fn` Function passed in.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var urlSanitizationNode = $document[0].createElement('a'),\n        startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n            };\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);\n      return function publicLinkFn(scope, cloneConnectFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n\n        // Attach scope only to non-text nodes.\n        for(var i = 0, ii = $linkNode.length; i<ii; i++) {\n          var node = $linkNode[i];\n          if (node.nodeType == 1 /* element */ || node.nodeType == 9 /* document */) {\n            $linkNode.eq(i).data('$scope', scope);\n          }\n        }\n        safeAddClass($linkNode, 'ng-scope');\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);\n        return $linkNode;\n      };\n    }\n\n    function wrongMode(localName, mode) {\n      throw Error(\"Unsupported '\" + mode + \"' for '\" + localName + \"'.\");\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes to compile\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the\n     *        rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} max directive priority\n     * @returns {?function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {\n      var linkFns = [],\n          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;\n\n      for(var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, maxPriority);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)\n            : null;\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)\n            ? null\n            : compileNodes(nodeList[i].childNodes,\n                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);\n\n        linkFns.push(nodeLinkFn);\n        linkFns.push(childLinkFn);\n        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var stableNodeList = [];\n        for (i = 0, ii = nodeList.length; i < ii; i++) {\n          stableNodeList.push(nodeList[i]);\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new(isObject(nodeLinkFn.scope));\n              jqLite(node).data('$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n            childTranscludeFn = nodeLinkFn.transclude;\n            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {\n              nodeLinkFn(childLinkFn, childScope, node, $rootElement,\n                  (function(transcludeFn) {\n                    return function(cloneFn) {\n                      var transcludeScope = scope.$new();\n                      transcludeScope.$$transcluded = true;\n\n                      return transcludeFn(transcludeScope, cloneFn).\n                          bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));\n                    };\n                  })(childTranscludeFn || transcludeFn)\n              );\n            } else {\n              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);\n            }\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);\n          }\n        }\n      }\n    }\n\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            attr = nAttrs[j];\n            if (attr.specified) {\n              name = attr.name;\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              attrs[nName] = value = trim((msie && name == 'href')\n                ? decodeURIComponent(node.getAttribute(name, 2))\n                : attr.value);\n              if (getBooleanAttrName(node, nName)) {\n                attrs[nName] = true; // presence means true\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n\n    /**\n     * Once the directives have been collected their compile functions is executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached..\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this\n     *        argument has the root jqLite array so that we can replace widgets on it.\n     * @returns linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {\n      var terminalPriority = -Number.MAX_VALUE,\n          preLinkFns = [],\n          postLinkFns = [],\n          newScopeDirective = null,\n          newIsolateScopeDirective = null,\n          templateDirective = null,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          transcludeDirective,\n          childTranscludeFn = transcludeFn,\n          controllerDirectives,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);\n          if (isObject(directiveValue)) {\n            safeAddClass($compileNode, 'ng-isolate-scope');\n            newIsolateScopeDirective = directive;\n          }\n          safeAddClass($compileNode, 'ng-scope');\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (directiveValue = directive.controller) {\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);\n          transcludeDirective = directive;\n          terminalPriority = directive.priority;\n          if (directiveValue == 'element') {\n            $template = jqLite(compileNode);\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith($rootElement, jqLite($template[0]), compileNode);\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority);\n          } else {\n            $template = jqLite(JQLiteClone(compileNode)).contents();\n            $compileNode.html(''); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if ((directiveValue = directive.template)) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            $template = jqLite('<div>' +\n                                 trim(directiveValue) +\n                               '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);\n            }\n\n            replaceWith($rootElement, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that were already applied and those that weren't\n            // - collect directives from the template, add them to the second group and sort them\n            // - append the second group with new directives to the first group\n            directives = directives.concat(\n                collectDirectives(\n                    compileNode,\n                    directives.splice(i + 1, directives.length - (i + 1)),\n                    newTemplateAttrs\n                )\n            );\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),\n              nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,\n              childTranscludeFn);\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;\n      nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post) {\n        if (pre) {\n          pre.require = directive.require;\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          post.require = directive.require;\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(require, $element) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = $element[retrievalMethod]('$' + require + 'Controller');\n          if (!value && !optional) {\n            throw Error(\"No controller: \" + require);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(require, $element));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n        } else {\n          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        }\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])\\s*(\\w*)\\s*$/;\n\n          var parentScope = scope.$parent || scope;\n\n          forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {\n            var match = definiton.match(LOCAL_REGEXP) || [],\n                attrName = match[2]|| scopeName,\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet;\n\n            scope.$$isolateBindings[scopeName] = mode + attrName;\n\n            switch (mode) {\n\n              case '@': {\n                attrs.$observe(attrName, function(value) {\n                  scope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = parentScope;\n                break;\n              }\n\n              case '=': {\n                parentGet = $parse(attrs[attrName]);\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = scope[scopeName] = parentGet(parentScope);\n                  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +\n                      ' (directive: ' + newIsolateScopeDirective.name + ')');\n                };\n                lastValue = scope[scopeName] = parentGet(parentScope);\n                scope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(parentScope);\n\n                  if (parentValue !== scope[scopeName]) {\n                    // we are out of sync and need to copy\n                    if (parentValue !== lastValue) {\n                      // parent changed and it has precedence\n                      lastValue = scope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(parentScope, parentValue = lastValue = scope[scopeName]);\n                    }\n                  }\n                  return parentValue;\n                });\n                break;\n              }\n\n              case '&': {\n                parentGet = $parse(attrs[attrName]);\n                scope[scopeName] = function(locals) {\n                  return parentGet(parentScope, locals);\n                }\n                break;\n              }\n\n              default: {\n                throw Error('Invalid isolate scope definition for directive ' +\n                    newIsolateScopeDirective.name + ': ' + definiton);\n              }\n            }\n          });\n        }\n\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: boundTranscludeFn\n            };\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            $element.data(\n                '$' + directive.name + 'Controller',\n                $controller(controller, locals));\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = 0, ii = postLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.require, $element));\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n      }\n    }\n\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority) {\n      var match = false;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              tDirectives.push(directive);\n              match = true;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key]) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,\n        $rootElement, replace, childTranscludeFn) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            controller: null, templateUrl: null, transclude: null, scope: null\n          });\n\n      $compileNode.html('');\n\n      $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template;\n\n          content = denormalizeTemplate(content);\n\n          if (replace) {\n            $template = jqLite('<div>' + trim(content) + '</div>').contents();\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            collectDirectives(compileNode, directives, tempTemplateAttrs);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, childTranscludeFn);\n          afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);\n\n\n          while(linkQueue.length) {\n            var controller = linkQueue.pop(),\n                linkRootElement = linkQueue.pop(),\n                beforeTemplateLinkNode = linkQueue.pop(),\n                scope = linkQueue.pop(),\n                linkNode = compileNode;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              // it was cloned therefore we have to clone as well.\n              linkNode = JQLiteClone(compileNode);\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n            }\n\n            afterTemplateNodeLinkFn(function() {\n              beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);\n            }, scope, linkNode, $rootElement, controller);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw Error('Failed to load template: ' + config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(controller);\n        } else {\n          afterTemplateNodeLinkFn(function() {\n            beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);\n          }, scope, node, rootElement, controller);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      return b.priority - a.priority;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw Error('Multiple directives [' + previousDirective.name + ', ' +\n          directive.name + '] asking for ' + what + ' on: ' +  startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: valueFn(function textInterpolateLinkFn(scope, node) {\n            var parent = node.parent(),\n                bindings = parent.data('$binding') || [];\n            bindings.push(interpolateFn);\n            safeAddClass(parent.data('$binding', bindings), 'ng-binding');\n            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n              node[0].nodeValue = value;\n            });\n          })\n        });\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n\n      directives.push({\n        priority: 100,\n        compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {\n          var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n          if (name === 'class') {\n            // we need to interpolate classes again, in the case the element was replaced\n            // and therefore the two class attrs got merged - we want to interpolate the result\n            interpolateFn = $interpolate(attr[name], true);\n          }\n\n          attr[name] = undefined;\n          ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n          (attr.$$observers && attr.$$observers[name].$$scope || scope).\n            $watch(interpolateFn, function interpolateFnWatchAction(value) {\n              attr.$set(name, value);\n            });\n        })\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *    in the root of the tree.\n     * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,\n     *    but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, $element, newNode) {\n      var oldNode = $element[0],\n          parent = oldNode.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == oldNode) {\n            $rootElement[i] = newNode;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, oldNode);\n      }\n\n      newNode[jqLite.expando] = oldNode[jqLite.expando];\n      $element[0] = newNode;\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * All of these will become 'myDirective':\n *   my:DiRective\n *   my-directive\n *   x-my-directive\n *   data-my:directive\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc object\n * @name ng.$compile.directive.Attributes\n * @description\n *\n * A shared object between directive compile / linking functions which contains normalized DOM element\n * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed\n * since all of these are treated as equivalent in Angular:\n *\n *          <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n */\n\n/**\n * @ngdoc property\n * @name ng.$compile.directive.Attributes#$attr\n * @propertyOf ng.$compile.directive.Attributes\n * @returns {object} A map of DOM element attribute names to the normalized name. This is\n *          needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$compile.directive.Attributes#$set\n * @methodOf ng.$compile.directive.Attributes\n * @function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\n/**\n * @ngdoc object\n * @name ng.$controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n\n  /**\n   * @ngdoc function\n   * @name ng.$controllerProvider#register\n   * @methodOf ng.$controllerProvider\n   * @param {string} name Controller name\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    if (isObject(name)) {\n      extend(controllers, name)\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just simple call to {@link AUTO.$injector $injector}, but extracted into\n     * a service, so that one can override this service with {@link https://gist.github.com/1649788\n     * BC version}.\n     */\n    return function(constructor, locals) {\n      if(isString(constructor)) {\n        var name = constructor;\n        constructor = controllers.hasOwnProperty(name)\n            ? controllers[name]\n            : getter(locals.$scope, name, true) || getter($window, name, true);\n\n        assertArgFn(constructor, name, true);\n      }\n\n      return $injector.instantiate(constructor, locals);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`\n * element.\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc function\n * @name ng.$exceptionHandler\n * @requires $log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log){\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$interpolateProvider\n * @function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#startSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$interpolateProvider#endSymbol\n   * @methodOf ng.$interpolateProvider\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', function($parse) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc function\n     * @name ng.$interpolate\n     * @function\n     *\n     * @requires $parse\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n       <pre>\n         var $interpolate = ...; // injected\n         var exp = $interpolate('Hello {{name}}!');\n         expect(exp({name:'Angular'}).toEqual('Hello Angular!');\n       </pre>\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @returns {function(context)} an interpolation function which is used to compute the interpolated\n     *    string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          for(var i = 0, ii = length, part; i<ii; i++) {\n            if (typeof (part = parts[i]) == 'function') {\n              part = part(context);\n              if (part == null || part == undefined) {\n                part = '';\n              } else if (typeof part != 'string') {\n                part = toJson(part);\n              }\n            }\n            concat[i] = part;\n          }\n          return concat.join('');\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#startSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name ng.$interpolate#endSymbol\n     * @methodOf ng.$interpolate\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    }\n\n    return $interpolate;\n  }];\n}\n\nvar URL_MATCH = /^([^:]+):\\/\\/(\\w+:{0,1}\\w*@)?([\\w\\.-]*)(:([0-9]+))?(\\/[^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    PATH_MATCH = /^([^\\?#]*)?(\\?([^#]*))?(#(.*))?$/,\n    HASH_MATCH = PATH_MATCH,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction stripHash(url) {\n  return url.split('#')[0];\n}\n\n\nfunction matchUrl(url, obj) {\n  var match = URL_MATCH.exec(url);\n\n  match = {\n      protocol: match[1],\n      host: match[3],\n      port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,\n      path: match[6] || '/',\n      search: match[8],\n      hash: match[10]\n    };\n\n  if (obj) {\n    obj.$$protocol = match.protocol;\n    obj.$$host = match.host;\n    obj.$$port = match.port;\n  }\n\n  return match;\n}\n\n\nfunction composeProtocolHostPort(protocol, host, port) {\n  return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);\n}\n\n\nfunction pathPrefixFromBase(basePath) {\n  return basePath.substr(0, basePath.lastIndexOf('/'));\n}\n\n\nfunction convertToHtml5Url(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already html5 url\n  if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||\n      match.hash.indexOf(hashPrefix) !== 0) {\n    return url;\n  // convert hashbang url -> html5 url\n  } else {\n    return composeProtocolHostPort(match.protocol, match.host, match.port) +\n           pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);\n  }\n}\n\n\nfunction convertToHashbangUrl(url, basePath, hashPrefix) {\n  var match = matchUrl(url);\n\n  // already hashbang url\n  if (decodeURIComponent(match.path) == basePath) {\n    return url;\n  // convert html5 url -> hashbang url\n  } else {\n    var search = match.search && '?' + match.search || '',\n        hash = match.hash && '#' + match.hash || '',\n        pathPrefix = pathPrefixFromBase(basePath),\n        path = match.path.substr(pathPrefix.length);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +\n           '#' + hashPrefix + path + search + hash;\n  }\n}\n\n\n/**\n * LocationUrl represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} url HTML5 url\n * @param {string} pathPrefix\n */\nfunction LocationUrl(url, pathPrefix, appBaseUrl) {\n  pathPrefix = pathPrefix || '';\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(newAbsoluteUrl) {\n    var match = matchUrl(newAbsoluteUrl, this);\n\n    if (match.path.indexOf(pathPrefix) !== 0) {\n      throw Error('Invalid url \"' + newAbsoluteUrl + '\", missing path prefix \"' + pathPrefix + '\" !');\n    }\n\n    this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));\n    this.$$search = parseKeyValue(match.search);\n    this.$$hash = match.hash && decodeURIComponent(match.hash) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    pathPrefix + this.$$url;\n  };\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is disabled or not supported\n *\n * @constructor\n * @param {string} url Legacy url\n * @param {string} hashPrefix Prefix for hash part (containing path and search)\n */\nfunction LocationHashbangUrl(url, hashPrefix, appBaseUrl) {\n  var basePath;\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var match = matchUrl(url, this);\n\n\n    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {\n      throw Error('Invalid url \"' + url + '\", missing hash prefix \"' + hashPrefix + '\" !');\n    }\n\n    basePath = match.path + (match.search ? '?' + match.search : '');\n    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));\n    if (match[1]) {\n      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);\n    } else {\n      this.$$path = '';\n    }\n\n    this.$$search = parseKeyValue(match[3]);\n    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +\n                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');\n  };\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return absoluteLinkUrl;\n    }\n  }\n\n\n  this.$$parse(url);\n}\n\n\nLocationUrl.prototype = {\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#absUrl\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#url\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url, replace) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '', replace);\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#protocol\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#host\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#port\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#path\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {string=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#search\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   * @param {string|object<string,string>=} search New search params - string or hash object\n   * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a\n   *    single search parameter. If the value is `null`, the parameter will be deleted.\n   *\n   * @return {string} search\n   */\n  search: function(search, paramValue) {\n    if (isUndefined(search))\n      return this.$$search;\n\n    if (isDefined(paramValue)) {\n      if (paramValue === null) {\n        delete this.$$search[search];\n      } else {\n        this.$$search[search] = paramValue;\n      }\n    } else {\n      this.$$search = isString(search) ? parseKeyValue(search) : search;\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#hash\n   * @methodOf ng.$location\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {string=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', identity),\n\n  /**\n   * @ngdoc method\n   * @name ng.$location#replace\n   * @methodOf ng.$location\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nLocationHashbangUrl.prototype = inherit(LocationUrl.prototype);\n\nfunction LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {\n  LocationHashbangUrl.apply(this, arguments);\n\n\n  this.$$rewriteAppUrl = function(absoluteLinkUrl) {\n    if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {\n      return appBaseUrl + baseExtra + '#' + hashPrefix  + absoluteLinkUrl.substr(appBaseUrl.length);\n    }\n  }\n}\n\nLocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc object\n * @name ng.$location\n *\n * @requires $browser\n * @requires $sniffer\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular\n * Services: Using $location}\n */\n\n/**\n * @ngdoc object\n * @name ng.$locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#hashPrefix\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc property\n   * @name ng.$locationProvider#html5Mode\n   * @methodOf ng.$locationProvider\n   * @description\n   * @param {string=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        basePath,\n        pathPrefix,\n        initUrl = $browser.url(),\n        initUrlParts = matchUrl(initUrl),\n        appBaseUrl;\n\n    if (html5Mode) {\n      basePath = $browser.baseHref() || '/';\n      pathPrefix = pathPrefixFromBase(basePath);\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          pathPrefix + '/';\n\n      if ($sniffer.history) {\n        $location = new LocationUrl(\n          convertToHtml5Url(initUrl, basePath, hashPrefix),\n          pathPrefix, appBaseUrl);\n      } else {\n        $location = new LocationHashbangInHtml5Url(\n          convertToHashbangUrl(initUrl, basePath, hashPrefix),\n          hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));\n      }\n    } else {\n      appBaseUrl =\n          composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +\n          (initUrlParts.path || '') +\n          (initUrlParts.search ? ('?' + initUrlParts.search) : '') +\n          '#' + hashPrefix + '/';\n\n      $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);\n    }\n\n    $rootElement.bind('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href'),\n          rewrittenUrl = $location.$$rewriteAppUrl(absHref);\n\n      if (absHref && !elm.attr('target') && rewrittenUrl) {\n        // update location manually\n        $location.$$parse(rewrittenUrl);\n        $rootScope.$apply();\n        event.preventDefault();\n        // hack to work around FF6 bug 684208 when scenario runner clicks on links\n        window.angular['ff-684208-preventDefault'] = true;\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          afterLocationChange(oldUrl);\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc object\n * @name ng.$log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * @example\n   <example>\n     <file name=\"script.js\">\n       function LogCtrl($scope, $log) {\n         $scope.$log = $log;\n         $scope.message = 'Hello World!';\n       }\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogCtrl\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\nfunction $LogProvider(){\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name ng.$log#log\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#warn\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#info\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name ng.$log#error\n       * @methodOf ng.$log\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error')\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      if (logFn.apply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2);\n      }\n    }\n  }];\n}\n\nvar OPERATORS = {\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\nfunction lex(text, csp){\n  var tokens = [],\n      token,\n      index = 0,\n      json = [],\n      ch,\n      lastCh = ':'; // can start regexp\n\n  while (index < text.length) {\n    ch = text.charAt(index);\n    if (is('\"\\'')) {\n      readString(ch);\n    } else if (isNumber(ch) || is('.') && isNumber(peek())) {\n      readNumber();\n    } else if (isIdent(ch)) {\n      readIdent();\n      // identifiers can only be if the preceding char was a { or ,\n      if (was('{,') && json[0]=='{' &&\n         (token=tokens[tokens.length-1])) {\n        token.json = token.text.indexOf('.') == -1;\n      }\n    } else if (is('(){}[].,;:')) {\n      tokens.push({\n        index:index,\n        text:ch,\n        json:(was(':[,') && is('{[')) || is('}]:,')\n      });\n      if (is('{[')) json.unshift(ch);\n      if (is('}]')) json.shift();\n      index++;\n    } else if (isWhitespace(ch)) {\n      index++;\n      continue;\n    } else {\n      var ch2 = ch + peek(),\n          fn = OPERATORS[ch],\n          fn2 = OPERATORS[ch2];\n      if (fn2) {\n        tokens.push({index:index, text:ch2, fn:fn2});\n        index += 2;\n      } else if (fn) {\n        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});\n        index += 1;\n      } else {\n        throwError(\"Unexpected next character \", index, index+1);\n      }\n    }\n    lastCh = ch;\n  }\n  return tokens;\n\n  function is(chars) {\n    return chars.indexOf(ch) != -1;\n  }\n\n  function was(chars) {\n    return chars.indexOf(lastCh) != -1;\n  }\n\n  function peek() {\n    return index + 1 < text.length ? text.charAt(index + 1) : false;\n  }\n  function isNumber(ch) {\n    return '0' <= ch && ch <= '9';\n  }\n  function isWhitespace(ch) {\n    return ch == ' ' || ch == '\\r' || ch == '\\t' ||\n           ch == '\\n' || ch == '\\v' || ch == '\\u00A0'; // IE treats non-breaking space as \\u00A0\n  }\n  function isIdent(ch) {\n    return 'a' <= ch && ch <= 'z' ||\n           'A' <= ch && ch <= 'Z' ||\n           '_' == ch || ch == '$';\n  }\n  function isExpOperator(ch) {\n    return ch == '-' || ch == '+' || isNumber(ch);\n  }\n\n  function throwError(error, start, end) {\n    end = end || index;\n    throw Error(\"Lexer Error: \" + error + \" at column\" +\n        (isDefined(start)\n            ? \"s \" + start +  \"-\" + index + \" [\" + text.substring(start, end) + \"]\"\n            : \" \" + end) +\n        \" in expression [\" + text + \"].\");\n  }\n\n  function readNumber() {\n    var number = \"\";\n    var start = index;\n    while (index < text.length) {\n      var ch = lowercase(text.charAt(index));\n      if (ch == '.' || isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = peek();\n        if (ch == 'e' && isExpOperator(peekCh)) {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            peekCh && isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (isExpOperator(ch) &&\n            (!peekCh || !isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      index++;\n    }\n    number = 1 * number;\n    tokens.push({index:start, text:number, json:true,\n      fn:function() {return number;}});\n  }\n  function readIdent() {\n    var ident = \"\",\n        start = index,\n        lastDot, peekIndex, methodName;\n\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      if (ch == '.' || isIdent(ch) || isNumber(ch)) {\n        if (ch == '.') lastDot = index;\n        ident += ch;\n      } else {\n        break;\n      }\n      index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = index;\n      while(peekIndex < text.length) {\n        var ch = text.charAt(peekIndex);\n        if (ch == '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          index = peekIndex;\n          break;\n        }\n        if(isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index:start,\n      text:ident\n    };\n\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = token.json = OPERATORS[ident];\n    } else {\n      var getter = getterFn(ident, csp);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value);\n        }\n      });\n    }\n\n    tokens.push(token);\n\n    if (methodName) {\n      tokens.push({\n        index:lastDot,\n        text: '.',\n        json: false\n      });\n      tokens.push({\n        index: lastDot + 1,\n        text: methodName,\n        json: false\n      });\n    }\n  }\n\n  function readString(quote) {\n    var start = index;\n    index++;\n    var string = \"\";\n    var rawString = quote;\n    var escape = false;\n    while (index < text.length) {\n      var ch = text.charAt(index);\n      rawString += ch;\n      if (escape) {\n        if (ch == 'u') {\n          var hex = text.substring(index + 1, index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            throwError( \"Invalid unicode escape [\\\\u\" + hex + \"]\");\n          index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          if (rep) {\n            string += rep;\n          } else {\n            string += ch;\n          }\n        }\n        escape = false;\n      } else if (ch == '\\\\') {\n        escape = true;\n      } else if (ch == quote) {\n        index++;\n        tokens.push({\n          index:start,\n          text:rawString,\n          string:string,\n          json:true,\n          fn:function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      index++;\n    }\n    throwError(\"Unterminated quote\", start);\n  }\n}\n\n/////////////////////////////////////////\n\nfunction parser(text, json, $filter, csp){\n  var ZERO = valueFn(0),\n      value,\n      tokens = lex(text, csp),\n      assignment = _assignment,\n      functionCall = _functionCall,\n      fieldAccess = _fieldAccess,\n      objectIndex = _objectIndex,\n      filterChain = _filterChain;\n\n  if(json){\n    // The extra level of aliasing is here, just in case the lexer misses something, so that\n    // we prevent any accidental execution in JSON.\n    assignment = logicalOR;\n    functionCall =\n      fieldAccess =\n      objectIndex =\n      filterChain =\n        function() { throwError(\"is not valid json\", {text:text, index:0}); };\n    value = primary();\n  } else {\n    value = statements();\n  }\n  if (tokens.length !== 0) {\n    throwError(\"is an unexpected token\", tokens[0]);\n  }\n  return value;\n\n  ///////////////////////////////////\n  function throwError(msg, token) {\n    throw Error(\"Syntax Error: Token '\" + token.text +\n      \"' \" + msg + \" at column \" +\n      (token.index + 1) + \" of the expression [\" +\n      text + \"] starting at [\" + text.substring(token.index) + \"].\");\n  }\n\n  function peekToken() {\n    if (tokens.length === 0)\n      throw Error(\"Unexpected end of expression: \" + text);\n    return tokens[0];\n  }\n\n  function peek(e1, e2, e3, e4) {\n    if (tokens.length > 0) {\n      var token = tokens[0];\n      var t = token.text;\n      if (t==e1 || t==e2 || t==e3 || t==e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  }\n\n  function expect(e1, e2, e3, e4){\n    var token = peek(e1, e2, e3, e4);\n    if (token) {\n      if (json && !token.json) {\n        throwError(\"is not valid json\", token);\n      }\n      tokens.shift();\n      return token;\n    }\n    return false;\n  }\n\n  function consume(e1){\n    if (!expect(e1)) {\n      throwError(\"is unexpected, expecting [\" + e1 + \"]\", peek());\n    }\n  }\n\n  function unaryFn(fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, right);\n    };\n  }\n\n  function binaryFn(left, fn, right) {\n    return function(self, locals) {\n      return fn(self, locals, left, right);\n    };\n  }\n\n  function statements() {\n    var statements = [];\n    while(true) {\n      if (tokens.length > 0 && !peek('}', ')', ';', ']'))\n        statements.push(filterChain());\n      if (!expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return statements.length == 1\n          ? statements[0]\n          : function(self, locals){\n            var value;\n            for ( var i = 0; i < statements.length; i++) {\n              var statement = statements[i];\n              if (statement)\n                value = statement(self, locals);\n            }\n            return value;\n          };\n      }\n    }\n  }\n\n  function _filterChain() {\n    var left = expression();\n    var token;\n    while(true) {\n      if ((token = expect('|'))) {\n        left = binaryFn(left, token.fn, filter());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function filter() {\n    var token = expect();\n    var fn = $filter(token.text);\n    var argsFn = [];\n    while(true) {\n      if ((token = expect(':'))) {\n        argsFn.push(expression());\n      } else {\n        var fnInvoke = function(self, locals, input){\n          var args = [input];\n          for ( var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  }\n\n  function expression() {\n    return assignment();\n  }\n\n  function _assignment() {\n    var left = logicalOR();\n    var right;\n    var token;\n    if ((token = expect('='))) {\n      if (!left.assign) {\n        throwError(\"implies assignment but [\" +\n          text.substring(0, token.index) + \"] can not be assigned to\", token);\n      }\n      right = logicalOR();\n      return function(self, locals){\n        return left.assign(self, right(self, locals), locals);\n      };\n    } else {\n      return left;\n    }\n  }\n\n  function logicalOR() {\n    var left = logicalAND();\n    var token;\n    while(true) {\n      if ((token = expect('||'))) {\n        left = binaryFn(left, token.fn, logicalAND());\n      } else {\n        return left;\n      }\n    }\n  }\n\n  function logicalAND() {\n    var left = equality();\n    var token;\n    if ((token = expect('&&'))) {\n      left = binaryFn(left, token.fn, logicalAND());\n    }\n    return left;\n  }\n\n  function equality() {\n    var left = relational();\n    var token;\n    if ((token = expect('==','!='))) {\n      left = binaryFn(left, token.fn, equality());\n    }\n    return left;\n  }\n\n  function relational() {\n    var left = additive();\n    var token;\n    if ((token = expect('<', '>', '<=', '>='))) {\n      left = binaryFn(left, token.fn, relational());\n    }\n    return left;\n  }\n\n  function additive() {\n    var left = multiplicative();\n    var token;\n    while ((token = expect('+','-'))) {\n      left = binaryFn(left, token.fn, multiplicative());\n    }\n    return left;\n  }\n\n  function multiplicative() {\n    var left = unary();\n    var token;\n    while ((token = expect('*','/','%'))) {\n      left = binaryFn(left, token.fn, unary());\n    }\n    return left;\n  }\n\n  function unary() {\n    var token;\n    if (expect('+')) {\n      return primary();\n    } else if ((token = expect('-'))) {\n      return binaryFn(ZERO, token.fn, unary());\n    } else if ((token = expect('!'))) {\n      return unaryFn(token.fn, unary());\n    } else {\n      return primary();\n    }\n  }\n\n\n  function primary() {\n    var primary;\n    if (expect('(')) {\n      primary = filterChain();\n      consume(')');\n    } else if (expect('[')) {\n      primary = arrayDeclaration();\n    } else if (expect('{')) {\n      primary = object();\n    } else {\n      var token = expect();\n      primary = token.fn;\n      if (!primary) {\n        throwError(\"not a primary expression\", token);\n      }\n    }\n\n    var next, context;\n    while ((next = expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = fieldAccess(primary);\n      } else {\n        throwError(\"IMPOSSIBLE\");\n      }\n    }\n    return primary;\n  }\n\n  function _fieldAccess(object) {\n    var field = expect().text;\n    var getter = getterFn(field, csp);\n    return extend(\n        function(self, locals) {\n          return getter(object(self, locals), locals);\n        },\n        {\n          assign:function(self, value, locals) {\n            return setter(object(self, locals), field, value);\n          }\n        }\n    );\n  }\n\n  function _objectIndex(obj) {\n    var indexFn = expression();\n    consume(']');\n    return extend(\n      function(self, locals){\n        var o = obj(self, locals),\n            i = indexFn(self, locals),\n            v, p;\n\n        if (!o) return undefined;\n        v = o[i];\n        if (v && v.then) {\n          p = v;\n          if (!('$$v' in v)) {\n            p.$$v = undefined;\n            p.then(function(val) { p.$$v = val; });\n          }\n          v = v.$$v;\n        }\n        return v;\n      }, {\n        assign:function(self, value, locals){\n          return obj(self, locals)[indexFn(self, locals)] = value;\n        }\n      });\n  }\n\n  function _functionCall(fn, contextGetter) {\n    var argsFn = [];\n    if (peekToken().text != ')') {\n      do {\n        argsFn.push(expression());\n      } while (expect(','));\n    }\n    consume(')');\n    return function(self, locals){\n      var args = [],\n          context = contextGetter ? contextGetter(self, locals) : self;\n\n      for ( var i = 0; i < argsFn.length; i++) {\n        args.push(argsFn[i](self, locals));\n      }\n      var fnPtr = fn(self, locals) || noop;\n      // IE stupidity!\n      return fnPtr.apply\n          ? fnPtr.apply(context, args)\n          : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n    };\n  }\n\n  // This is used with json array declaration\n  function arrayDeclaration () {\n    var elementFns = [];\n    if (peekToken().text != ']') {\n      do {\n        elementFns.push(expression());\n      } while (expect(','));\n    }\n    consume(']');\n    return function(self, locals){\n      var array = [];\n      for ( var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    };\n  }\n\n  function object () {\n    var keyValues = [];\n    if (peekToken().text != '}') {\n      do {\n        var token = expect(),\n        key = token.string || token.text;\n        consume(\":\");\n        var value = expression();\n        keyValues.push({key:key, value:value});\n      } while (expect(','));\n    }\n    consume('}');\n    return function(self, locals){\n      var object = {};\n      for ( var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        var value = keyValue.value(self, locals);\n        object[keyValue.key] = value;\n      }\n      return object;\n    };\n  }\n}\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue) {\n  var element = path.split('.');\n  for (var i = 0; element.length > 1; i++) {\n    var key = element.shift();\n    var propertyObj = obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n  }\n  obj[element.shift()] = setValue;\n  return setValue;\n}\n\n/**\n * Return the value accesible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {string} path path to traverse\n * @param {boolean=true} bindFnToScope\n * @returns value as accesbile by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\nvar getterFnCache = {};\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4) {\n  return function(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n        promise;\n\n    if (pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key0];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key1 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key1];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key2 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key2];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key3 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key3];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    if (!key4 || pathVal === null || pathVal === undefined) return pathVal;\n\n    pathVal = pathVal[key4];\n    if (pathVal && pathVal.then) {\n      if (!(\"$$v\" in pathVal)) {\n        promise = pathVal;\n        promise.$$v = undefined;\n        promise.then(function(val) { promise.$$v = val; });\n      }\n      pathVal = pathVal.$$v;\n    }\n    return pathVal;\n  };\n};\n\nfunction getterFn(path, csp) {\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  if (csp) {\n    fn = (pathKeysLength < 6)\n        ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])\n        : function(scope, locals) {\n          var i = 0, val\n          do {\n            val = cspSafeGetterFn(\n                    pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]\n                  )(scope, locals);\n\n            locals = undefined; // clear after first iteration\n            scope = val;\n          } while (i < pathKeysLength);\n          return val;\n        }\n  } else {\n    var code = 'var l, fn, p;\\n';\n    forEach(pathKeys, function(key, index) {\n      code += 'if(s === null || s === undefined) return s;\\n' +\n              'l=s;\\n' +\n              's='+ (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((k&&k.hasOwnProperty(\"' + key + '\"))?k:s)') + '[\"' + key + '\"]' + ';\\n' +\n              'if (s && s.then) {\\n' +\n                ' if (!(\"$$v\" in s)) {\\n' +\n                  ' p=s;\\n' +\n                  ' p.$$v = undefined;\\n' +\n                  ' p.then(function(v) {p.$$v=v;});\\n' +\n                  '}\\n' +\n                ' s=s.$$v\\n' +\n              '}\\n';\n    });\n    code += 'return s;';\n    fn = Function('s', 'k', code); // s=scope, k=locals\n    fn.toString = function() { return code; };\n  }\n\n  return getterFnCache[path] = fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc function\n * @name ng.$parse\n * @function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * <pre>\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * </pre>\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n *      are evaluated against (tipically a scope object).\n *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n *      `context`.\n *\n *    The return function also has an `assign` property, if the expression is assignable, which\n *    allows one to set values to expressions.\n *\n */\nfunction $ParseProvider() {\n  var cache = {};\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    return function(exp) {\n      switch(typeof exp) {\n        case 'string':\n          return cache.hasOwnProperty(exp)\n            ? cache[exp]\n            : cache[exp] =  parser(exp, false, $filter, $sniffer.csp);\n        case 'function':\n          return exp;\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name ng.$q\n * @requires $rootScope\n *\n * @description\n * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise APIs are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * <pre>\n *   // for the purpose of this example let's assume that variables `$q` and `scope` are\n *   // available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       // since this fn executes async in a future turn of the event loop, we need to wrap\n *       // our code into an $apply call so that the model changes are properly observed.\n *       scope.$apply(function() {\n *         if (okToGreet(name)) {\n *           deferred.resolve('Hello, ' + name + '!');\n *         } else {\n *           deferred.reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       });\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * </pre>\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of\n * [guarantees that promise and deferred APIs make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as APIs\n * that can be used for signaling the successful or unsuccessful completion of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved\n *   or rejected calls one of the success or error callbacks asynchronously as soon as the result\n *   is available. The callbacks are called with a single argument the result or rejection reason.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback` or `errorCallback`.\n *\n *\n * # Chaining promises\n *\n * Because calling `then` api of a promise returns a new derived promise, it is easily possible\n * to create a chain of promises:\n *\n * <pre>\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and its value will be\n *   // the result of promiseA incremented by 1\n * </pre>\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful apis like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are three main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - $q promises are recognized by the templating engine in angular, which means that in templates\n *   you can treat promises attached to a scope as if they were the resulting values.\n * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n *\n *  # Testing\n *\n *  <pre>\n *    it('should simulate promise', inject(function($q, $rootScope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n *\n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n *\n *      // Simulate resolving of promise\n *      deferred.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n *\n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    });\n *  </pre>\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc\n   * @name ng.$q#defer\n   * @methodOf ng.$q\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(reject(reason));\n      },\n\n\n      promise: {\n        then: function(callback, errback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((callback || defaultCallback)(value));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((errback || defaultErrback)(reason));\n            } catch(e) {\n              exceptionHandler(e);\n              result.reject(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback);\n          }\n\n          return result.promise;\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (value && value.then) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#reject\n   * @methodOf ng.$q\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * <pre>\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * </pre>\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve((errback || defaultErrback)(reason));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#when\n   * @methodOf ng.$q\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with an object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value corresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  var when = function(value, callback, errback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (callback || defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (errback || defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc\n   * @name ng.$q#all\n   * @methodOf ng.$q\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>} promises An array of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array of values,\n   *   each value corresponding to the promise at the same index in the `promises` array. If any of\n   *   the promises is resolved with a rejection, this resulting promise will be resolved with the\n   *   same rejection.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = promises.length,\n        results = [];\n\n    if (counter) {\n      forEach(promises, function(promise, index) {\n        ref(promise).then(function(value) {\n          if (index in results) return;\n          results[index] = value;\n          if (!(--counter)) deferred.resolve(results);\n        }, function(reason) {\n          if (index in results) return;\n          deferred.reject(reason);\n        });\n      });\n    } else {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes. See {@link ng.$route $route} for an example.\n */\nfunction $RouteProvider(){\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#when\n   * @methodOf ng.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    `path` can contain named groups starting with a colon (`:name`). All characters up to the\n   *    next slash are matched and stored in `$routeParams` under the given `name` when the route\n   *    matches.\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly\n   *      created scope or the name of a {@link angular.Module#controller registered controller}\n   *      if passed as a string.\n   *    - `template` – `{string=}` –  html template as a string that should be used by\n   *      {@link ng.directive:ngView ngView} or\n   *      {@link ng.directive:ngInclude ngInclude} directives.\n   *      this property takes precedence over `templateUrl`.\n   *    - `templateUrl` – `{string=}` – path to an html template that should be used by\n   *      {@link ng.directive:ngView ngView}.\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, they will be\n   *      resolved and converted to a value before the controller is instantiated and the\n   *      `$routeChangeSuccess` event is fired. The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is resolved\n   *        before its value is injected into the controller.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()\n   *    changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = extend({reloadOnSearch: true}, route);\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n          ? path.substr(0, path.length-1)\n          : path +'/';\n\n      routes[redirectPath] = {redirectTo: path};\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ng.$routeProvider#otherwise\n   * @methodOf ng.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',\n      function( $rootScope,   $location,   $routeParams,   $q,   $injector,   $http,   $templateCache) {\n\n    /**\n     * @ngdoc object\n     * @name ng.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * Is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * You can define routes through {@link ng.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView}\n     * directive and the {@link ng.$routeParams $routeParams} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngView\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngView', [], function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"scenario.js\">\n         it('should load and compile correct template', function() {\n           element('a:contains(\"Moby: Ch1\")').click();\n           var content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element('a:contains(\"Scarlet\")').click();\n           sleep(2); // promises are not part of scenario waiting\n           content = element('.doc-example-live [ng-view]').text();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeStart\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occurs.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeSuccess\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ng.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeChangeError\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ng.$route#$routeUpdate\n     * @eventOf ng.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ng.$route#reload\n           * @methodOf ng.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ng.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param when {string} route when template to match the url against\n     * @return {?Object}\n     */\n    function switchRouteMatcher(on, when) {\n      // TODO(i): this code is convoluted and inefficient, we should construct the route matching\n      //   regex only once and then reuse it\n\n      // Escape regexp special characters.\n      when = '^' + when.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\") + '$';\n      var regex = '',\n          params = [],\n          dst = {};\n\n      var re = /:(\\w+)/g,\n          paramMatch,\n          lastMatchedIndex = 0;\n\n      while ((paramMatch = re.exec(when)) !== null) {\n        // Find each :param in `when` and replace it with a capturing group.\n        // Append all other sections of when unchanged.\n        regex += when.slice(lastMatchedIndex, paramMatch.index);\n        regex += '([^\\\\/]*)';\n        params.push(paramMatch[1]);\n        lastMatchedIndex = re.lastIndex;\n      }\n      // Append trailing path part.\n      regex += when.substr(lastMatchedIndex);\n\n      var match = on.match(new RegExp(regex));\n      if (match) {\n        forEach(params, function(name, index) {\n          dst[name] = match[index + 1];\n        });\n      }\n      return match ? dst : null;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$route === last.$route\n          && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var keys = [],\n                  values = [],\n                  template;\n\n              forEach(next.resolve || {}, function(value, key) {\n                keys.push(key);\n                values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));\n              });\n              if (isDefined(template = next.template)) {\n              } else if (isDefined(template = next.templateUrl)) {\n                template = $http.get(template, {cache: $templateCache}).\n                    then(function(response) { return response.data; });\n              }\n              if (isDefined(template)) {\n                keys.push('$template');\n                values.push(template);\n              }\n              return $q.all(values).then(function(values) {\n                var locals = {};\n                forEach(values, function(value, index) {\n                  locals[keys[index]] = value;\n                });\n                return locals;\n              });\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), path))) {\n          match = inherit(route, {\n            params: extend({}, $location.search(), params),\n            pathParams: params});\n          match.$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parametrs\n     */\n    function interpolate(string, params) {\n      var result = [];\n      forEach((string||'').split(':'), function(segment, i) {\n        if (i == 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$routeParams\n * @requires $route\n *\n * @description\n * Current set of route parameters. The route parameters are a combination of the\n * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters\n * are extracted when the {@link ng.$route $route} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = valueFn({});\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope ware heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive from speed as well as memory:\n *   - no closures, instead ups prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the begging (shift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using array would be slow since inserts in meddle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc function\n * @name ng.$rootScopeProvider#digestTtl\n * @methodOf ng.$rootScopeProvider\n * @description\n *\n * Sets the number of digest iteration the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc object\n * @name ng.$rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide\n * event processing life-cycle. See {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse',\n      function( $injector,   $exceptionHandler,   $parse) {\n\n    /**\n     * @ngdoc function\n     * @name ng.$rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link AUTO.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * <pre>\n        angular.injector(['ng']).invoke(function($rootScope) {\n           var scope = $rootScope.$new();\n           scope.salutation = 'Hello';\n           scope.name = 'World';\n\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$watch('name', function() {\n             scope.greeting = scope.salutation + ' ' + scope.name + '!';\n           }); // initialize the watch\n\n           expect(scope.greeting).toEqual(undefined);\n           scope.name = 'Misko';\n           // still old value, since watches have not been called yet\n           expect(scope.greeting).toEqual(undefined);\n\n           scope.$digest(); // fire all  the watches\n           expect(scope.greeting).toEqual('Hello Misko!');\n        });\n     * </pre>\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * <pre>\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * </pre>\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be provided\n     *     for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *     append/override services provided by `providers`. This is handy when unit-testing and having\n     *     the need to override a default service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$listeners = {};\n      this.$$isolateBindings = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name ng.$rootScope.Scope#$id\n     * @propertyOf ng.$rootScope.Scope\n     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for\n     *   debugging.\n     */\n\n\n    Scope.prototype = {\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$new\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and\n       * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope\n       * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for\n       * the scope and its child scopes to be permanently detached from the parent and thus stop\n       * participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate if true then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var Child,\n            child;\n\n        if (isFunction(isolate)) {\n          // TODO: remove at some point\n          throw Error('API-CHANGE: Use $controller to instantiate controllers.');\n        }\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          Child = function() {}; // should be anonymous; This is so that when the minifier munges\n            // the name it does not become random set of chars. These will then show up as class\n            // name in the debugger.\n          Child.prototype = this;\n          child = new Child();\n          child.$id = nextUid();\n        }\n        child['this'] = child;\n        child.$$listeners = {};\n        child.$parent = this;\n        child.$$asyncQueue = [];\n        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$watch\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and\n       *   should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}\n       *   reruns when it detects changes the `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). The inequality is determined according to\n       *   {@link angular.equals} function. To save the value of the object for later comparison, the\n       *   {@link angular.copy} function is used. It also means that watching complex options will\n       *   have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This\n       *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration\n       *   limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is\n       * detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       * # Example\n       * <pre>\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a\n       *    call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.\n       *\n       * @param {boolean=} objectEquality Compare object for equality rather than for reference.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function() {\n          arrayRemove(array, watcher);\n        };\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$digest\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Process all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.\n       * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the\n       * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are\n       * firing. This means that it is possible to get into an infinite loop. This function will throw\n       * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.\n       *\n       * Usually you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a\n       * {@link ng.$compileProvider#directive directives}) will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function  with {@link ng.$rootScope.Scope#$watch $watch()}\n       * with no `listener`.\n       *\n       * You may have a need to call `$digest()` from within unit-tests, to simulate the scope\n       * life-cycle.\n       *\n       * # Example\n       * <pre>\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // no variable change\n           expect(scope.counter).toEqual(0);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(1);\n       * </pre>\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg;\n\n        beginPhase('$digest');\n\n        do {\n          dirty = false;\n          current = target;\n          do {\n            asyncQueue = current.$$asyncQueue;\n            while(asyncQueue.length) {\n              try {\n                current.$eval(asyncQueue.shift());\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            }\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if ((value = watch.get(current)) !== (last = watch.last) &&\n                      !(watch.eq\n                          ? equals(value, last)\n                          : (typeof value == 'number' && typeof last == 'number'\n                             && isNaN(value) && isNaN(last)))) {\n                    dirty = true;\n                    watch.last = watch.eq ? copy(value) : value;\n                    watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                    if (ttl < 5) {\n                      logIdx = 4 - ttl;\n                      if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                      logMsg = (isFunction(watch.exp))\n                          ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                          : watch.exp;\n                      logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                      watchLog[logIdx].push(logMsg);\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          if(dirty && !(ttl--)) {\n            clearPhase();\n            throw Error(TTL + ' $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: ' + toJson(watchLog));\n          }\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name ng.$rootScope.Scope#$destroy\n       * @eventOf ng.$rootScope.Scope\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       */\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$destroy\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it chance to\n       * perform any necessary cleanup.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if ($rootScope == this || this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // This is bogus code that works around Chrome's GC leak\n        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = null;\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$eval\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the `expression` on the current scope returning the result. Any exceptions in the\n       * expression are propagated (uncaught). This is useful when evaluating Angular expressions.\n       *\n       * # Example\n       * <pre>\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * </pre>\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$evalAsync\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that:\n       *\n       *   - it will execute in the current script execution context (before any DOM rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        this.$$asyncQueue.push(expr);\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$apply\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular framework.\n       * (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life-cycle\n       * of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * <pre>\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * </pre>\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression\n       *    was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$on\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of\n       * event life cycle.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: Name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event\n       *     propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event, args...)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        return function() {\n          namedListeners[indexOf(namedListeners, listener)] = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$emit\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event traverses upwards toward the root scope and calls all registered\n       * listeners along the way. The event will stop propagating if one of the listeners cancels it.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              namedListeners[i].apply(null, listenerArgs);\n              if (stopPropagation) return event;\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name ng.$rootScope.Scope#$broadcast\n       * @methodOf ng.$rootScope.Scope\n       * @function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified.\n       * Afterwards, the event propagates to all direct and indirect scopes of the current scope and\n       * calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        do {\n          current = next;\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        } while ((current = next));\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw Error($rootScope.$$phase + ' already in progress');\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's unique we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', function($window) {\n    var eventSupport = {},\n        android = int((/android (\\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n      history: !!($window.history && $window.history.pushState && !(android < 4)),\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!$window.document.documentMode || $window.document.documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = $window.document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      // TODO(i): currently there is no way to feature detect CSP without triggering alerts\n      csp: false\n    };\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overriden, removed or mocked for testing.\n *\n * All expressions are evaluated with respect to current scope so they don't\n * suffer from window globality.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <input ng-init=\"$window = $service('$window'); greeting='Hello World!'\" type=\"text\" ng-model=\"greeting\" />\n       <button ng-click=\"$window.alert(greeting)\">ALERT</button>\n     </doc:source>\n     <doc:scenario>\n     </doc:scenario>\n   </doc:example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      if (parsed[key]) {\n        parsed[key] += ', ' + val;\n      } else {\n        parsed[key] = val;\n      }\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(function|Array.<function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\n  var $config = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data, true);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*',\n        'X-Requested-With': 'XMLHttpRequest'\n      },\n      post: {'Content-Type': 'application/json;charset=utf-8'},\n      put:  {'Content-Type': 'application/json;charset=utf-8'}\n    }\n  };\n\n  var providerResponseInterceptors = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http'),\n        responseInterceptors = [];\n\n    forEach(providerResponseInterceptors, function(interceptor) {\n      responseInterceptors.push(\n          isString(interceptor)\n              ? $injector.get(interceptor)\n              : $injector.invoke(interceptor)\n      );\n    });\n\n\n    /**\n     * @ngdoc function\n     * @name ng.$http\n     * @requires $httpBackend\n     * @requires $browser\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest\n     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,\n     * it is important to familiarize yourself with these apis and guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an http request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * <pre>\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * </pre>\n     *\n     * Since the returned value of calling the $http function is a Promise object, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the api signature and type info below for more\n     * details.\n     *\n     * A response status code that falls in the [200, 300) range is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Shortcut methods\n     *\n     * Since all invocation of the $http service require definition of the http method and url and\n     * POST and PUT requests require response body/data to be provided as well, shortcut methods\n     * were created to simplify using the api:\n     *\n     * <pre>\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * </pre>\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain http headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     *   - `X-Requested-With: XMLHttpRequest`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from this configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with name equal to the lower-cased http method name, e.g.\n     * `$httpProvider.defaults.headers.get['My-Header']='value'`.\n     *\n     * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar\n     * fassion as described above.\n     *\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - if the `data` property of the request config object contains an object, serialize it into\n     *   JSON format.\n     *\n     * Response transformations:\n     *\n     *  - if XSRF prefix is detected, strip it (see Security Considerations section below)\n     *  - if json response is detected, deserialize it using a JSON parser\n     *\n     * To override these transformation locally, specify transform functions as `transformRequest`\n     * and/or `transformResponse` properties of the config object. To globally override the default\n     * transforms, override the `$httpProvider.defaults.transformRequest` and\n     * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching set the configuration property `cache` to `true`. When the cache is\n     * enabled, `$http` stores the response from the server in local cache. Next time the\n     * response is served from the cache without sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same url that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response for the first request.\n     *\n     *\n     * # Response interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * <pre>\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * </pre>\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     *   JSON Vulnerability}\n     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx\n     * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into\n     * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * <pre>\n     * ['one','two']\n     * </pre>\n     *\n     * which is vulnerable to attack, your server can return:\n     * <pre>\n     * )]}',\n     * ['one','two']\n     * </pre>\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides following mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that\n     * runs on your domain could read the cookie, your server can be assured that the XHR came from\n     * JavaScript running on your domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have read the token. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript making\n     * up its own tokens). We recommend that the token is a digest of your site's authentication\n     * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned to\n     *      `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.\n     *    - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number}` – timeout in milliseconds.\n     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the\n     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n     *      requests with credentials} for more information.\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n      <example>\n        <file name=\"index.html\">\n          <div ng-controller=\"FetchCtrl\">\n            <select ng-model=\"method\">\n              <option>GET</option>\n              <option>JSONP</option>\n            </select>\n            <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n            <button ng-click=\"fetch()\">fetch</button><br>\n            <button ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">Sample JSONP</button>\n            <button ng-click=\"updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">Invalid JSONP</button>\n            <pre>http status code: {{status}}</pre>\n            <pre>http response data: {{data}}</pre>\n          </div>\n        </file>\n        <file name=\"script.js\">\n          function FetchCtrl($scope, $http, $templateCache) {\n            $scope.method = 'GET';\n            $scope.url = 'http-hello.html';\n\n            $scope.fetch = function() {\n              $scope.code = null;\n              $scope.response = null;\n\n              $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n                success(function(data, status) {\n                  $scope.status = status;\n                  $scope.data = data;\n                }).\n                error(function(data, status) {\n                  $scope.data = data || \"Request failed\";\n                  $scope.status = status;\n              });\n            };\n\n            $scope.updateModel = function(method, url) {\n              $scope.method = method;\n              $scope.url = url;\n            };\n          }\n        </file>\n        <file name=\"http-hello.html\">\n          Hello, $http!\n        </file>\n        <file name=\"scenario.js\">\n          it('should make an xhr GET request', function() {\n            element(':button:contains(\"Sample GET\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Hello, \\$http!/);\n          });\n\n          it('should make a JSONP request to angularjs.org', function() {\n            element(':button:contains(\"Sample JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('200');\n            expect(binding('data')).toMatch(/Super Hero!/);\n          });\n\n          it('should make JSONP request to invalid URL and invoke the error handler',\n              function() {\n            element(':button:contains(\"Invalid JSONP\")').click();\n            element(':button:contains(\"fetch\")').click();\n            expect(binding('status')).toBe('0');\n            expect(binding('data')).toBe('Request failed');\n          });\n        </file>\n      </example>\n     */\n    function $http(config) {\n      config.method = uppercase(config.method);\n\n      var reqTransformFn = config.transformRequest || $config.transformRequest,\n          respTransformFn = config.transformResponse || $config.transformResponse,\n          defHeaders = $config.headers,\n          reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},\n              defHeaders.common, defHeaders[lowercase(config.method)], config.headers),\n          reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),\n          promise;\n\n      // strip content-type if data is undefined\n      if (isUndefined(config.data)) {\n        delete reqHeaders['Content-Type'];\n      }\n\n      // send request\n      promise = sendReq(config, reqData, reqHeaders);\n\n\n      // transform future response\n      promise = promise.then(transformResponse, transformResponse);\n\n      // apply interceptors\n      forEach(responseInterceptors, function(interceptor) {\n        promise = interceptor(promise);\n      });\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, respTransformFn)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#get\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `GET` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#delete\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#head\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#jsonp\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     Should contain `JSON_CALLBACK` string.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#post\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `POST` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name ng.$http#put\n     * @methodOf ng.$http\n     *\n     * @description\n     * Shortcut method to perform `PUT` request\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put');\n\n        /**\n         * @ngdoc property\n         * @name ng.$http#defaults\n         * @propertyOf ng.$http\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = $config;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if (config.cache && config.method == 'GET') {\n        cache = isObject(config.cache) ? config.cache : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (cachedResp) {\n          if (cachedResp.then) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));\n            } else {\n              resolvePromise(cachedResp, 200, {});\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n      // if we won't have the response in cache, send the request to the backend\n      if (!cachedResp) {\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString)]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString);\n        $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n          if (!params) return url;\n          var parts = [];\n          forEachSorted(params, function(value, key) {\n            if (value == null || value == undefined) return;\n            if (isObject(value)) {\n              value = toJson(value);\n            }\n            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n          });\n          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n        }\n\n\n  }];\n}\nvar XHR = window.XMLHttpRequest || function() {\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\"); } catch (e1) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\"); } catch (e2) {}\n  try { return new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e3) {}\n  throw new Error(\"This browser does not support XMLHttpRequest.\");\n};\n\n\n/**\n * @ngdoc object\n * @name ng.$httpBackend\n * @requires $browser\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,\n        $document[0], $window.location.protocol.replace(':', ''));\n  }];\n}\n\nfunction createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n      };\n\n      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          function() {\n        if (callbacks[callbackId].data) {\n          completeRequest(callback, 200, callbacks[callbackId].data);\n        } else {\n          completeRequest(callback, -2);\n        }\n        delete callbacks[callbackId];\n      });\n    } else {\n      var xhr = new XHR();\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (value) xhr.setRequestHeader(key, value);\n      });\n\n      var status;\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        if (xhr.readyState == 4) {\n          var responseHeaders = xhr.getAllResponseHeaders();\n\n          // TODO(vojta): remove once Firefox 21 gets released.\n          // begin: workaround to overcome Firefox CORS http response headers bug\n          // https://bugzilla.mozilla.org/show_bug.cgi?id=608735\n          // Firefox already patched in nightly. Should land in Firefox 21.\n\n          // CORS \"simple response headers\" http://www.w3.org/TR/cors/\n          var value,\n              simpleHeaders = [\"Cache-Control\", \"Content-Language\", \"Content-Type\",\n                                  \"Expires\", \"Last-Modified\", \"Pragma\"];\n          if (!responseHeaders) {\n            responseHeaders = \"\";\n            forEach(simpleHeaders, function (header) {\n              var value = xhr.getResponseHeader(header);\n              if (value) {\n                  responseHeaders += header + \": \" + value + \"\\n\";\n              }\n            });\n          }\n          // end of the workaround.\n\n          completeRequest(callback, status || xhr.status, xhr.responseText,\n                          responseHeaders);\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      xhr.send(post || '');\n\n      if (timeout > 0) {\n        $browserDefer(function() {\n          status = -1;\n          xhr.abort();\n        }, timeout);\n      }\n    }\n\n\n    function completeRequest(callback, status, response, headersString) {\n      // URL_MATCH is defined in src/service/location.js\n      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];\n\n      // fix status code for file protocol (it's always 0)\n      status = (protocol == 'file') ? (response ? 200 : 404) : status;\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status == 1223 ? 204 : status;\n\n      callback(status, response, headersString);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'),\n        doneWrapper = function() {\n          rawDocument.body.removeChild(script);\n          if (done) done();\n        };\n\n    script.type = 'text/javascript';\n    script.src = url;\n\n    if (msie) {\n      script.onreadystatechange = function() {\n        if (/loaded|complete/.test(script.readyState)) doneWrapper();\n      };\n    } else {\n      script.onload = script.onerror = doneWrapper;\n    }\n\n    rawDocument.body.appendChild(script);\n  }\n}\n\n/**\n * @ngdoc object\n * @name ng.$locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December'\n                .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout\n      * @requires $browser\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a the timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, who's execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId, cleanup;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      cleanup = function() {\n        delete deferreds[promise.$$timeoutId];\n      };\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n      promise.then(cleanup, cleanup);\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc function\n      * @name ng.$timeout#cancel\n      * @methodOf ng.$timeout\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To\n * achieve this a filter definition consists of a factory function which is annotated with dependencies and is\n * responsible for creating a the filter function.\n *\n * <pre>\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * </pre>\n *\n * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`.\n * <pre>\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * </pre>\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer\n * Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression | [ filter_name ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  function register(name, factory) {\n    return $provide.factory(name + suffix, factory);\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    }\n  }];\n\n  ////////////////////////////////////////\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: Predicate that results in a substring match using the value of `expression`\n *     string. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above.\n *\n *   - `function`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"å><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th><tr>\n         <tr ng-repeat=\"friend in friends | filter:search\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         <tr>\n       </table>\n     </doc:source>\n     <doc:scenario>\n       it('should search across all fields when filtering with a string', function() {\n         input('searchText').enter('m');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Adam']);\n\n         input('searchText').enter('76');\n         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['John', 'Julie']);\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         input('search.$').enter('i');\n         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Mike', 'Julie']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction filterFilter() {\n  return function(array, expression) {\n    if (!isArray(array)) return array;\n    var predicates = [];\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n    var search = function(obj, text){\n      if (text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case \"boolean\":\n        case \"number\":\n        case \"string\":\n          return ('' + obj).toLowerCase().indexOf(text) > -1;\n        case \"object\":\n          for ( var objKey in obj) {\n            if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n              return true;\n            }\n          }\n          return false;\n        case \"array\":\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case \"boolean\":\n      case \"number\":\n      case \"string\":\n        expression = {$:expression};\n      case \"object\":\n        for (var key in expression) {\n          if (key == '$') {\n            (function() {\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(value, text);\n              });\n            })();\n          } else {\n            (function() {\n              var path = key;\n              var text = (''+expression[key]).toLowerCase();\n              if (!text) return;\n              predicates.push(function(value) {\n                return search(getter(value, path), text);\n              });\n            })();\n          }\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  }\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.amount = 1234.56;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): {{amount | currency}}<br>\n         custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should init with 1234.56', function() {\n         expect(binding('amount | currency')).toBe('$1,234.56');\n         expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         input('amount').enter('-1234');\n         expect(binding('amount | currency')).toBe('($1,234.00)');\n         expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n       });\n     </doc:scenario>\n   </doc:example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.val = 1234.56789;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: {{val | number}}<br>\n         No fractions: {{val | number:0}}<br>\n         Negative number: {{-val | number:4}}\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should format numbers', function() {\n         expect(binding('val | number')).toBe('1,234.568');\n         expect(binding('val | number:0')).toBe('1,235');\n         expect(binding('-val | number:4')).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         input('val').enter('3374.333');\n         expect(binding('val | number')).toBe('3,374.333');\n         expect(binding('val | number:0')).toBe('3,374');\n         expect(binding('-val | number:4')).toBe('-3,374.3330');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (isNaN(number) || !isFinite(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    var pow = Math.pow(10, fractionSize);\n    number = Math.round(number * pow) / pow;\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (var i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize && fractionSize !== \"0\") formatedText += decimalSep + fraction.substr(0, fractionSize);\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var zone = -1 * date.getTimezoneOffset();\n  var paddedZone = (zone >= 0) ? \"+\" : \"\";\n\n  paddedZone += padNumber(zone / 60, 2) + padNumber(Math.abs(zone % 60), 2);\n\n  return paddedZone;\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n *   (e.g. `\"h o''clock\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is\n *    specified in the string input, the time is considered to be in the local timezone.\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           {{1288323623006 | date:'medium'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>\n     </doc:source>\n     <doc:scenario>\n       it('should format date', function() {\n         expect(binding(\"1288323623006 | date:'medium'\")).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} (\\-|\\+)?\\d{4}/);\n         expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </doc:scenario>\n   </doc:example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n  function jsonStringToDate(string){\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0;\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      if (NUMBER_STRING.test(date)) {\n        date = int(date);\n      } else {\n        date = jsonStringToDate(date);\n      }\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n   <doc:example>\n     <doc:source>\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </doc:source>\n     <doc:scenario>\n       it('should jsonify filtered objects', function() {\n         expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array containing only a specified number of elements in an array. The elements\n * are taken from either the beginning or the end of the source array, as specified by the\n * value and sign (positive or negative) of `limit`.\n *\n * Note: This function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more information about Angular arrays.\n *\n * @param {Array} array Source array to be limited.\n * @param {string|Number} limit The length of the returned array. If the `limit` number is\n *     positive, `limit` number of items from the beginning of the source array are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array are\n *     copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`\n *     elements.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.numbers = [1,2,3,4,5,6,7,8,9];\n           $scope.limit = 3;\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Limit {{numbers}} to: <input type=\"integer\" ng-model=\"limit\">\n         <p>Output: {{ numbers | limitTo:limit }}</p>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should limit the numer array to first three items', function() {\n         expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');\n       });\n\n       it('should update the output when -3 is entered', function() {\n         input('limit').enter(-3);\n         expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');\n       });\n\n       it('should not exceed the maximum size of input array', function() {\n         input('limit').enter(100);\n         expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nfunction limitToFilter(){\n  return function(array, limit) {\n    if (!(array instanceof Array)) return array;\n    limit = int(limit);\n    var out = [],\n      i, n;\n\n    // check that array is iterable\n    if (!array || !(array instanceof Array))\n      return out;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > array.length)\n      limit = array.length;\n    else if (limit < -array.length)\n      limit = -array.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = array.length + limit;\n      n = array.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(array[i]);\n    }\n\n    return out;\n  }\n}\n\n/**\n * @ngdoc function\n * @name ng.filter:orderBy\n * @function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate.\n *\n * Note: this function is used to augment the `Array` type in Angular expressions. See\n * {@link ng.$filter} for more informaton about Angular arrays.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n *      ascending or descending sort order (for example, +name or -name).\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.friends =\n               [{name:'John', phone:'555-1212', age:10},\n                {name:'Mary', phone:'555-9876', age:19},\n                {name:'Mike', phone:'555-4321', age:21},\n                {name:'Adam', phone:'555-5678', age:35},\n                {name:'Julie', phone:'555-8765', age:29}]\n           $scope.predicate = '-age';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           <tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           <tr>\n         </table>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should be reverse ordered by aged', function() {\n         expect(binding('predicate')).toBe('-age');\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '29', '21', '19', '10']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n       });\n\n       it('should reorder the table when user selects different predicate', function() {\n         element('.doc-example-live a:contains(\"Name\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n           toEqual(['35', '10', '29', '19', '21']);\n\n         element('.doc-example-live a:contains(\"Phone\")').click();\n         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n         expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n       });\n     </doc:scenario>\n   </doc:example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!isArray(array)) return array;\n    if (!sortPredicate) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        get = $parse(predicate);\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    var arrayCopy = [];\n    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (t1 == \"string\") v1 = v1.toLowerCase();\n        if (t1 == \"string\") v2 = v2.toLowerCase();\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    }\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of html A tag, so that the default action is prevented when href\n * attribute is empty.\n *\n * The reasoning for this change is to allow easy creation of action links with `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * `<a href=\"\" ng-click=\"model.$save()\">Save</a>`\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n\n    if (msie <= 8) {\n\n      // turn <a href ng-click=\"..\">link</a> into a stylable link in IE\n      // but only if it doesn't have name attribute, in which case it's an anchor\n      if (!attr.href && !attr.name) {\n        attr.$set('href', '');\n      }\n\n      // add a comment node to anchors to workaround IE bug that causes element content to be reset\n      // to new attribute content if attribute is updated with value containing @ and element also\n      // contains value with @\n      // see issue #1949\n      element.append(document.createComment('IE fix'));\n    }\n\n    return function(scope, element) {\n      element.bind('click', function(event){\n        // if we have no href url, then don't navigate anywhere.\n        if (!element.attr('href')) {\n          event.preventDefault();\n        }\n      });\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like {{hash}} in an href attribute makes\n * the page open to a wrong URL, if the user clicks that link before\n * angular has a chance to replace the {{hash}} with actual URL, the\n * link will be broken and will most likely return a 404 error.\n * The `ngHref` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example uses `link` variable inside `href` attribute:\n    <doc:example>\n      <doc:source>\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </doc:source>\n      <doc:scenario>\n        it('should execute ng-click but not reload when href without value', function() {\n          element('#link-1').click();\n          expect(input('value').val()).toEqual('1');\n          expect(element('#link-1').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element('#link-2').click();\n          expect(input('value').val()).toEqual('2');\n          expect(element('#link-2').attr('href')).toBe(\"\");\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n          element('#link-3').click();\n          expect(browser().window().path()).toEqual('/123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element('#link-4').click();\n          expect(input('value').val()).toEqual('4');\n          expect(element('#link-4').attr('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element('#link-5').click();\n          expect(input('value').val()).toEqual('5');\n          expect(element('#link-5').attr('href')).toBe(undefined);\n        });\n\n        it('should only change url when only ng-href', function() {\n          input('value').enter('6');\n          expect(element('#link-6').attr('href')).toBe('6');\n\n          element('#link-6').click();\n          expect(browser().location().url()).toEqual('/6');\n        });\n      </doc:scenario>\n    </doc:example>\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * <pre>\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * The correct way to write it:\n * <pre>\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * </pre>\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * <pre>\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * </pre>\n *\n * The HTML specs do not require browsers to preserve the special attributes such as disabled.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngDisabled` directive.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle button', function() {\n          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngDisabled Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as checked.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngChecked` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </doc:source>\n      <doc:scenario>\n        it('should check both checkBoxes', function() {\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n          input('master').check();\n          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {expression} ngChecked Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMultiple\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as multiple.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngMultiple` directive.\n *\n * @example\n     <doc:example>\n       <doc:source>\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n         <select id=\"select\" ng-multiple=\"checked\">\n           <option>Misko</option>\n           <option>Igor</option>\n           <option>Vojta</option>\n           <option>Di</option>\n         </select>\n       </doc:source>\n       <doc:scenario>\n         it('should toggle multiple', function() {\n           expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();\n           input('checked').check();\n           expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();\n         });\n       </doc:scenario>\n     </doc:example>\n *\n * @element SELECT\n * @param {expression} ngMultiple Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as readonly.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduce the `ngReadonly` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </doc:source>\n      <doc:scenario>\n        it('should toggle readonly attr', function() {\n          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n          input('checked').check();\n          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element INPUT\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specs do not require browsers to preserve the special attributes such as selected.\n * (The presence of them means true and absence means false)\n * This prevents the angular compiler from correctly retrieving the binding expression.\n * To solve this problem, we introduced the `ngSelected` directive.\n * @example\n    <doc:example>\n      <doc:source>\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </doc:source>\n      <doc:scenario>\n        it('should select Greetings!', function() {\n          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n          input('selected').check();\n          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n        });\n      </doc:scenario>\n    </doc:example>\n *\n * @element OPTION\n * @param {string} expression Angular expression that will be evaluated.\n */\n\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      compile: function() {\n        return function(scope, element, attr) {\n          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n            attr.$set(attrName, !!value);\n          });\n        };\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-href are interpolated\nforEach(['src', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        attr.$observe(normalized, function(value) {\n          if (!value)\n             return;\n\n          attr.$set(attrName, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect.\n          // we use attr[attrName] value since $set can sanitize the url.\n          if (msie) element.prop(attrName, attr[attrName]);\n        });\n      }\n    };\n  };\n});\n\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names) — such as `required`, `url` or `email`),\n *  - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {};\n\n  // init state\n  form.$name = attrs.name;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  form.$addControl = function(control) {\n    if (control.$name && !form.hasOwnProperty(control.$name)) {\n      form[control.$name] = control;\n    }\n  };\n\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n  };\n\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  form.$setDirty = function() {\n    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this\n * reason angular provides {@link ng.directive:ngForm `ngForm`} alias\n * which behaves identical to `<form>` but allows form nesting.\n *\n *\n * # CSS classes\n *  - `ng-valid` Is set if the form is valid.\n *  - `ng-invalid` Is set if the form is invalid.\n *  - `ng-pristine` Is set if the form is pristine.\n *  - `ng-dirty` Is set if the form is dirty.\n *\n *\n * # Submitting a form and preventing default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in application specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This\n * is because of the following form submission rules coming from the html spec:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.userType = 'guest';\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n         expect(binding('userType')).toEqual('guest');\n         expect(binding('myForm.input.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n         input('userType').enter('');\n         expect(binding('userType')).toEqual('');\n         expect(binding('myForm.input.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.bind('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              scope[alias] = controller;\n            }\n            if (parentFormCtrl) {\n              formElement.bind('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  scope[alias] = undefined;\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.text\n   *\n   * @description\n   * Standard HTML text input with angular data binding.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'guest';\n             $scope.word = /^\\w*$/;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('guest');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input('text').enter('hello world');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.number\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value = 12;\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.list.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n           expect(binding('value')).toEqual('12');\n           expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n           input('value').enter('');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if over max', function() {\n           input('value').enter('123');\n           expect(binding('value')).toEqual('');\n           expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.url\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'http://google.com';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('http://google.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.email\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.text = 'me@example.com';\n           }\n         </script>\n           <form name=\"myForm\" ng-controller=\"Ctrl\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n        </doc:source>\n        <doc:scenario>\n          it('should initialize to model', function() {\n            expect(binding('text')).toEqual('me@example.com');\n            expect(binding('myForm.input.$valid')).toEqual('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input('text').enter('');\n            expect(binding('text')).toEqual('');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input('text').enter('xxx');\n            expect(binding('myForm.input.$valid')).toEqual('false');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.radio\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.color = 'blue';\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"green\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('color')).toEqual('blue');\n\n            input('color').select('red');\n            expect(binding('color')).toEqual('red');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc inputType\n   * @name ng.directive:input.checkbox\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <doc:example>\n        <doc:source>\n         <script>\n           function Ctrl($scope) {\n             $scope.value1 = true;\n             $scope.value2 = 'YES'\n           }\n         </script>\n         <form name=\"myForm\" ng-controller=\"Ctrl\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </doc:source>\n        <doc:scenario>\n          it('should change state', function() {\n            expect(binding('value1')).toEqual('true');\n            expect(binding('value2')).toEqual('YES');\n\n            input('value1').check();\n            input('value2').check();\n            expect(binding('value1')).toEqual('false');\n            expect(binding('value2')).toEqual('NO');\n          });\n        </doc:scenario>\n      </doc:example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop\n};\n\n\nfunction isEmpty(value) {\n  return isUndefined(value) || value === '' || value === null || value !== value;\n}\n\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\n  var listener = function() {\n    var value = trim(element.val());\n\n    if (ctrl.$viewValue !== value) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(value);\n      });\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.bind('input', listener);\n  } else {\n    var timeout;\n\n    element.bind('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    });\n\n    // if user paste into input using mouse, we need \"change\" event to catch it\n    element.bind('change', listener);\n  }\n\n\n  ctrl.$render = function() {\n    element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator;\n\n  var validate = function(regexp, value) {\n    if (isEmpty(value) || regexp.test(value)) {\n      ctrl.$setValidity('pattern', true);\n      return value;\n    } else {\n      ctrl.$setValidity('pattern', false);\n      return undefined;\n    }\n  };\n\n  if (pattern) {\n    if (pattern.match(/^\\/(.*)\\/$/)) {\n      pattern = new RegExp(pattern.substr(1, pattern.length - 2));\n      patternValidator = function(value) {\n        return validate(pattern, value)\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);\n        }\n        return validate(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length < minlength) {\n        ctrl.$setValidity('minlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('minlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      if (!isEmpty(value) && value.length > maxlength) {\n        ctrl.$setValidity('maxlength', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('maxlength', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  ctrl.$formatters.push(function(value) {\n    return isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var min = parseFloat(attr.min);\n    var minValidator = function(value) {\n      if (!isEmpty(value) && value < min) {\n        ctrl.$setValidity('min', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('min', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var max = parseFloat(attr.max);\n    var maxValidator = function(value) {\n      if (!isEmpty(value) && value > max) {\n        ctrl.$setValidity('max', false);\n        return undefined;\n      } else {\n        ctrl.$setValidity('max', true);\n        return value;\n      }\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n\n    if (isEmpty(value) || isNumber(value)) {\n      ctrl.$setValidity('number', true);\n      return value;\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    if (isEmpty(value) || URL_REGEXP.test(value)) {\n      ctrl.$setValidity('url', true);\n      return value;\n    } else {\n      ctrl.$setValidity('url', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    if (isEmpty(value) || EMAIL_REGEXP.test(value)) {\n      ctrl.$setValidity('email', true);\n      return value;\n    } else {\n      ctrl.$setValidity('email', false);\n      return undefined;\n    }\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.bind('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.bind('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.user = {name: 'guest', last: 'visitor'};\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          input('user.name').enter('');\n          expect(binding('user')).toEqual('{\"last\":\"visitor\"}');\n          expect(binding('myForm.userName.$valid')).toEqual('false');\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          input('user.last').enter('');\n          expect(binding('user')).toEqual('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('true');\n          expect(binding('myForm.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          input('user.last').enter('xx');\n          expect(binding('user')).toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          input('user.last').enter('some ridiculously long name');\n          expect(binding('user'))\n            .toEqual('{\"name\":\"guest\"}');\n          expect(binding('myForm.lastName.$valid')).toEqual('false');\n          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);\n          expect(binding('myForm.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc object\n * @name ng.directive:ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Whenever the control reads value from the DOM, it executes\n *     all of these functions to sanitize / convert the value as well as validate.\n *\n * @property {Array.<Function>} $formatters Whenever the model value changes, it executes all of\n *     these functions to convert the value as well as validate.\n *\n * @property {Object} $error An bject hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS update, value formatting and parsing. It\n * specifically does not contain any logic which deals with DOM rendering or listening to\n * DOM events. The `NgModelController` is meant to be extended by other directives where, the\n * directive provides DOM manipulation and the `NgModelController` provides the data-binding.\n *\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * <example module=\"customControl\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', []).\n        directive('contenteditable', function() {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html(ngModel.$viewValue || '');\n              };\n\n              // Listen for change events to enable binding\n              element.bind('blur keyup change', function() {\n                scope.$apply(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                ngModel.$setViewValue(element.html());\n              }\n            }\n          };\n        });\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"scenario.js\">\n      it('should data-bind and become invalid', function() {\n        var contentEditable = element('[contenteditable]');\n\n        expect(contentEditable.text()).toEqual('Change me!');\n        input('userContent').enter('');\n        expect(contentEditable.text()).toEqual('');\n        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);\n      });\n    </file>\n * </example>\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',\n    function($scope, $exceptionHandler, $attr, $element, $parse) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel +\n        ' (' + startingTag($element) + ')');\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$render\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $element.\n      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setValidity\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    if ($error[validationErrorKey] === !isValid) return;\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name ng.directive:ngModel.NgModelController#$setViewValue\n   * @methodOf ng.directive:ngModel.NgModelController\n   *\n   * @description\n   * Read a value from view.\n   *\n   * This method should be called from within a DOM event handler.\n   * For example {@link ng.directive:input input} or\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It internally calls all `formatters` and if resulted value is valid, updates the model and\n   * calls all registered change listeners.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      })\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngModel\n *\n * @element input\n *\n * @description\n * Is directive that tells Angular to do two-way data binding. It works together with `input`,\n * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well.\n *\n * `ngModel` is responsible for:\n *\n * - binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require,\n * - providing validation behavior (i.e. required, number, email, url),\n * - keeping state of the control (valid/invalid, dirty/pristine, validation errors),\n * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),\n * - register the control with parent {@link ng.directive:form form}.\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link ng.directive:input.text text}\n *    - {@link ng.directive:input.checkbox checkbox}\n *    - {@link ng.directive:input.radio radio}\n *    - {@link ng.directive:input.number number}\n *    - {@link ng.directive:input.email email}\n *    - {@link ng.directive:input.url url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      element.bind('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChange\n * @restrict E\n *\n * @description\n * Evaluate given expression when user changes the input.\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n *\n * @example\n * <doc:example>\n *   <doc:source>\n *     <script>\n *       function Controller($scope) {\n *         $scope.counter = 0;\n *         $scope.change = function() {\n *           $scope.counter++;\n *         };\n *       }\n *     </script>\n *     <div ng-controller=\"Controller\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       debug = {{confirmed}}<br />\n *       counter = {{counter}}\n *     </div>\n *   </doc:source>\n *   <doc:scenario>\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(binding('counter')).toEqual('0');\n *       element('#ng-change-example1').click();\n *       expect(binding('counter')).toEqual('1');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element('#ng-change-example2').click();\n *       expect(binding('counter')).toEqual('0');\n *       expect(binding('confirmed')).toEqual('true');\n *     });\n *   </doc:scenario>\n * </doc:example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && (isEmpty(value) || value === false)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngList\n *\n * @description\n * Text input that converts between comma-separated string into an array of strings.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <doc:example>\n      <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.names = ['igor', 'misko', 'vojta'];\n         }\n       </script>\n       <form name=\"myForm\" ng-controller=\"Ctrl\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.list.$error.required\">\n           Required!</span>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </doc:source>\n      <doc:scenario>\n        it('should initialize to model', function() {\n          expect(binding('names')).toEqual('[\"igor\",\"misko\",\"vojta\"]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('true');\n        });\n\n        it('should be invalid if empty', function() {\n          input('names').enter('');\n          expect(binding('names')).toEqual('[]');\n          expect(binding('myForm.namesInput.$valid')).toEqual('false');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value, false);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBind\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when\n * it's desirable to put bindings into template that is momentarily displayed by the browser in its\n * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the\n * bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.name = 'Whirled';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('name')).toBe('Whirled');\n         using('.doc-example-live').input('name').enter('world');\n         expect(using('.doc-example-live').binding('name')).toBe('world');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindDirective = ngDirective(function(scope, element, attr) {\n  element.addClass('ng-binding').data('$binding', attr.ngBind);\n  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n    element.text(value == undefined ? '' : value);\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text should be replaced with the template in ngBindTemplate.\n * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}`\n * expressions. (This is required since some HTML elements\n * can not have SPAN elements such as TITLE, or OPTION to name a few.)\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <doc:example>\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.salutation = 'Hello';\n           $scope.name = 'World';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-bind', function() {\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Hello');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('World');\n         using('.doc-example-live').input('salutation').enter('Greetings');\n         using('.doc-example-live').input('name').enter('user');\n         expect(using('.doc-example-live').binding('salutation')).\n           toBe('Greetings');\n         expect(using('.doc-example-live').binding('name')).\n           toBe('user');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  }\n}];\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngBindHtmlUnsafe\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if\n * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too\n * restrictive and when you absolutely trust the source of the content you are binding to.\n *\n * See {@link ngSanitize.$sanitize $sanitize} docs for examples.\n *\n * @element ANY\n * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.\n */\nvar ngBindHtmlUnsafeDirective = [function() {\n  return function(scope, element, attr) {\n    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);\n    scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {\n      element.html(value || '');\n    });\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ngDirective(function(scope, element, attr) {\n    var oldVal = undefined;\n\n    scope.$watch(attr[name], ngClassWatchAction, true);\n\n    attr.$observe('class', function(value) {\n      var ngClass = scope.$eval(attr[name]);\n      ngClassWatchAction(ngClass, ngClass);\n    });\n\n\n    if (name !== 'ngClass') {\n      scope.$watch('$index', function($index, old$index) {\n        var mod = $index % 2;\n        if (mod !== old$index % 2) {\n          if (mod == selector) {\n            addClass(scope.$eval(attr[name]));\n          } else {\n            removeClass(scope.$eval(attr[name]));\n          }\n        }\n      });\n    }\n\n\n    function ngClassWatchAction(newVal) {\n      if (selector === true || scope.$index % 2 === selector) {\n        if (oldVal && (newVal !== oldVal)) {\n          removeClass(oldVal);\n        }\n        addClass(newVal);\n      }\n      oldVal = newVal;\n    }\n\n\n    function removeClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);\n    }\n\n\n    function addClass(classVal) {\n      if (isObject(classVal) && !isArray(classVal)) {\n        classVal = map(classVal, function(v, k) { if (v) return k });\n      }\n      if (classVal) {\n        element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);\n      }\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClass\n *\n * @description\n * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an\n * expression that represents all classes to be added.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the\n * new classes are added.\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .my-class {\n         color: red;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class', function() {\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:first').click();\n\n         expect(element('.doc-example-live span').prop('className')).\n           toMatch(/my-class/);\n\n         using('.doc-example-live').element(':button:last').click();\n\n         expect(element('.doc-example-live span').prop('className')).not().\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassOdd\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClassEven\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` works exactly as\n * {@link ng.directive:ngClass ngClass}, except it works in\n * conjunction with `ngRepeat` and takes affect only on odd (even) rows.\n *\n * This directive can be applied only within a scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element('.doc-example-live li:first span').prop('className')).\n           toMatch(/odd/);\n         expect(element('.doc-example-live li:last span').prop('className')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCloak\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but typically a fine-grained application is\n * prefered in order to benefit from progressive rendering of the browser view.\n *\n * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and\n *  `angular.min.js` files. Following is the css rule:\n *\n * <pre>\n * [ng\\:cloak], [ng-cloak], .ng-cloak {\n *   display: none;\n * }\n * </pre>\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, which\n * makes the compiled element visible.\n *\n * For the best result, `angular.js` script must be loaded in the head section of the html file;\n * alternatively, the css rule (above) must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ngCloak` in addition to `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <doc:example>\n     <doc:source>\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </doc:source>\n     <doc:scenario>\n       it('should remove the template directive and css class', function() {\n         expect(element('.doc-example-live #template1').attr('ng-cloak')).\n           not().toBeDefined();\n         expect(element('.doc-example-live #template2').attr('ng-cloak')).\n           not().toBeDefined();\n       });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngController\n *\n * @description\n * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — The Model is data in scope properties; scopes are attached to the DOM.\n * * View — The template (HTML with data bindings) is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class has\n *   methods that typically express the business logic behind the application.\n *\n * Note that an alternative way to define controllers is via the `{@link ng.$route}`\n * service.\n *\n * @element ANY\n * @scope\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Notice that the scope becomes the `this` for the\n * controller's instance. This allows for easy access to the view data from the controller. Also\n * notice that any changes to the data are automatically reflected in the View without the need\n * for a manual update.\n   <doc:example>\n     <doc:source>\n      <script>\n        function SettingsController($scope) {\n          $scope.name = \"John Smith\";\n          $scope.contacts = [\n            {type:'phone', value:'408 555 1212'},\n            {type:'email', value:'john.smith@example.org'} ];\n\n          $scope.greet = function() {\n           alert(this.name);\n          };\n\n          $scope.addContact = function() {\n           this.contacts.push({type:'email', value:'yourname@example.org'});\n          };\n\n          $scope.removeContact = function(contactToRemove) {\n           var index = this.contacts.indexOf(contactToRemove);\n           this.contacts.splice(index, 1);\n          };\n\n          $scope.clearContact = function(contact) {\n           contact.type = 'phone';\n           contact.value = '';\n          };\n        }\n      </script>\n      <div ng-controller=\"SettingsController\">\n        Name: <input type=\"text\" ng-model=\"name\"/>\n        [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n        Contact:\n        <ul>\n          <li ng-repeat=\"contact in contacts\">\n            <select ng-model=\"contact.type\">\n               <option>phone</option>\n               <option>email</option>\n            </select>\n            <input type=\"text\" ng-model=\"contact.value\"/>\n            [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n            | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n          </li>\n          <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n       </ul>\n      </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check controller', function() {\n         expect(element('.doc-example-live div>:input').val()).toBe('John Smith');\n         expect(element('.doc-example-live li:nth-child(1) input').val())\n           .toBe('408 555 1212');\n         expect(element('.doc-example-live li:nth-child(2) input').val())\n           .toBe('john.smith@example.org');\n\n         element('.doc-example-live li:first a:contains(\"clear\")').click();\n         expect(element('.doc-example-live li:first input').val()).toBe('');\n\n         element('.doc-example-live li:last a:contains(\"add\")').click();\n         expect(element('.doc-example-live li:nth-child(3) input').val())\n           .toBe('yourname@example.org');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@'\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngCsp\n * @priority 1000\n *\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n * This directive should be used on the root element of the application (typically the `<html>`\n * element or other element with the {@link ng.directive:ngApp ngApp}\n * directive).\n *\n * If enabled the performance of template expression evaluator will suffer slightly, so don't enable\n * this mode unless you need it.\n *\n * @element html\n */\n\nvar ngCspDirective = ['$sniffer', function($sniffer) {\n  return {\n    priority: 1000,\n    compile: function() {\n      $sniffer.csp = true;\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngClick\n *\n * @description\n * The ngClick allows you to specify custom behavior when\n * element is clicked.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. (Event object is available as `$event`)\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      count: {{count}}\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-click', function() {\n         expect(binding('count')).toBe('0');\n         element('.doc-example-live :button').click();\n         expect(binding('count')).toBe('1');\n       });\n     </doc:scenario>\n   </doc:example>\n */\n/*\n * A directive that allows creation of custom onclick handlers that are defined as angular\n * expressions and are compiled and executed within the current scope.\n *\n * Events that are handled via these handler are always configured not to propagate further.\n */\nvar ngEventDirectives = {};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),\n  function(name) {\n    var directiveName = directiveNormalize('ng-' + name);\n    ngEventDirectives[directiveName] = ['$parse', function($parse) {\n      return function(scope, element, attr) {\n        var fn = $parse(attr[directiveName]);\n        element.bind(lowercase(name), function(event) {\n          scope.$apply(function() {\n            fn(scope, {$event:event});\n          });\n        });\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on dblclick event.\n *\n * @element ANY\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * dblclick. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. (Event object is available as `$event`)\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page).\n *\n * @element form\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n      <script>\n        function Ctrl($scope) {\n          $scope.list = [];\n          $scope.text = 'hello';\n          $scope.submit = function() {\n            if (this.text) {\n              this.list.push(this.text);\n              this.text = '';\n            }\n          };\n        }\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"Ctrl\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-submit', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n         expect(input('text').val()).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(binding('list')).toBe('[]');\n         element('.doc-example-live #submit').click();\n         element('.doc-example-live #submit').click();\n         expect(binding('list')).toBe('[\"hello\"]');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngSubmitDirective = ngDirective(function(scope, element, attrs) {\n  element.bind('submit', function() {\n    scope.$apply(attrs.ngSubmit);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * Keep in mind that Same Origin Policy applies to included resources\n * (e.g. ngInclude won't work for cross-domain requests on all browsers and for\n *  file:// access on some browsers).\n *\n * @scope\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n     <div ng-controller=\"Ctrl\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div ng-include src=\"template.url\"></div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      function Ctrl($scope) {\n        $scope.templates =\n          [ { name: 'template1.html', url: 'template1.html'}\n          , { name: 'template2.html', url: 'template2.html'} ];\n        $scope.template = $scope.templates[0];\n      }\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"scenario.js\">\n      it('should load template1.html', function() {\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template1.html/);\n      });\n      it('should load template2.html', function() {\n       select('template').option('1');\n       expect(element('.doc-example-live [ng-include]').text()).\n         toMatch(/Content of template2.html/);\n      });\n      it('should change to blank', function() {\n       select('template').option('');\n       expect(element('.doc-example-live [ng-include]').text()).toEqual('');\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngInclude#$includeContentLoaded\n * @eventOf ng.directive:ngInclude\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile',\n                  function($http,   $templateCache,   $anchorScroll,   $compile) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n\n              if (childScope) childScope.$destroy();\n              childScope = scope.$new();\n\n              element.html(response);\n              $compile(element.contents())(childScope);\n\n              if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) clearContent();\n            });\n          } else clearContent();\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngInit\n *\n * @description\n * The `ngInit` directive specifies initialization tasks to be executed\n *  before the template enters execution mode during bootstrap.\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <doc:example>\n     <doc:source>\n    <div ng-init=\"greeting='Hello'; person='World'\">\n      {{greeting}} {{person}}!\n    </div>\n     </doc:source>\n     <doc:scenario>\n       it('should check greeting', function() {\n         expect(binding('greeting')).toBe('Hello');\n         expect(binding('person')).toBe('World');\n       });\n     </doc:scenario>\n   </doc:example>\n */\nvar ngInitDirective = ngDirective({\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngNonBindable\n * @priority 1000\n *\n * @description\n * Sometimes it is necessary to write code which looks like bindings but which should be left alone\n * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML.\n *\n * @element ANY\n *\n * @example\n * In this example there are two location where a simple binding (`{{}}`) is present, but the one\n * wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </doc:source>\n      <doc:scenario>\n       it('should check ng-non-bindable', function() {\n         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');\n         expect(using('.doc-example-live').element('div:last').text()).\n           toMatch(/1 \\+ 2/);\n       });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngPluralize\n * @restrict EA\n *\n * @description\n * # Overview\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js and the rules can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n * plural categories} in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a pural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. You will see the use of plural categories\n * and explicit number rules throughout later parts of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object so that Angular\n * can interpret it correctly.\n *\n * The following example shows how to configure ngPluralize:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *</pre>\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * <pre>\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * </pre>\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Marry and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bounded to.\n * @param {string} when The mapping between plural category to its correspoding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.person1 = 'Igor';\n            $scope.person2 = 'Misko';\n            $scope.personCount = 1;\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should show correct pluralized string', function() {\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                             toBe('1 person is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                                toBe('Igor is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('0');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                               toBe('Nobody is viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                                              toBe('Nobody is viewing.');\n\n          using('.doc-example-live').input('personCount').enter('2');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('2 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor and Misko are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('3');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('3 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and one other person are viewing.');\n\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:first').text()).\n                                            toBe('4 people are viewing.');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n                              toBe('Igor, Misko and 2 other people are viewing.');\n        });\n\n        it('should show data-binded names', function() {\n          using('.doc-example-live').input('personCount').enter('4');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Igor, Misko and 2 other people are viewing.');\n\n          using('.doc-example-live').input('person1').enter('Di');\n          using('.doc-example-live').input('person2').enter('Vojta');\n          expect(element('.doc-example-live ng-pluralize:last').text()).\n              toBe('Di, Vojta and 2 other people are viewing.');\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp),\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol();\n\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!whens[value]) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n *   * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)\n *   * `$first` – `{boolean}` – true if the repeated element is first in the iterator.\n *   * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.\n *   * `$last` – `{boolean}` – true if the repeated element is last in the iterator.\n *\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `track in cd.tracks`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n    <doc:example>\n      <doc:source>\n        <div ng-init=\"friends = [{name:'John', age:25}, {name:'Mary', age:28}]\">\n          I have {{friends.length}} friends. They are:\n          <ul>\n            <li ng-repeat=\"friend in friends\">\n              [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n            </li>\n          </ul>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-repeat', function() {\n           var r = using('.doc-example-live').repeater('ul li');\n           expect(r.count()).toBe(2);\n           expect(r.row(0)).toEqual([\"1\",\"John\",\"25\"]);\n           expect(r.row(1)).toEqual([\"2\",\"Mary\",\"28\"]);\n         });\n      </doc:scenario>\n    </doc:example>\n */\nvar ngRepeatDirective = ngDirective({\n  transclude: 'element',\n  priority: 1000,\n  terminal: true,\n  compile: function(element, attr, linker) {\n    return function(scope, iterStartElement, attr){\n      var expression = attr.ngRepeat;\n      var match = expression.match(/^\\s*(.+)\\s+in\\s+(.*)\\s*$/),\n        lhs, rhs, valueIdent, keyIdent;\n      if (! match) {\n        throw Error(\"Expected ngRepeat in form of '_item_ in _collection_' but got '\" +\n          expression + \"'.\");\n      }\n      lhs = match[1];\n      rhs = match[2];\n      match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n      if (!match) {\n        throw Error(\"'item' in 'item in collection' should be identifier or (key, value) but got '\" +\n            lhs + \"'.\");\n      }\n      valueIdent = match[3] || match[1];\n      keyIdent = match[2];\n\n      // Store a list of elements from previous run. This is a hash where key is the item from the\n      // iterator, and the value is an array of objects with following properties.\n      //   - scope: bound scope\n      //   - element: previous element.\n      //   - index: position\n      // We need an array of these objects since the same object can be returned from the iterator.\n      // We expect this to be a rare case.\n      var lastOrder = new HashQueueMap();\n\n      scope.$watch(function ngRepeatWatch(scope){\n        var index, length,\n            collection = scope.$eval(rhs),\n            cursor = iterStartElement,     // current position of the node\n            // Same as lastOrder but it has the current state. It will become the\n            // lastOrder on the next iteration.\n            nextOrder = new HashQueueMap(),\n            arrayLength,\n            childScope,\n            key, value, // key/value of iteration\n            array,\n            last;       // last object information {scope, element, index}\n\n\n\n        if (!isArray(collection)) {\n          // if object, extract keys, sort them and use to determine order of iteration over obj props\n          array = [];\n          for(key in collection) {\n            if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n              array.push(key);\n            }\n          }\n          array.sort();\n        } else {\n          array = collection || [];\n        }\n\n        arrayLength = array.length;\n\n        // we are not using forEach for perf reasons (trying to avoid #call)\n        for (index = 0, length = array.length; index < length; index++) {\n          key = (collection === array) ? index : array[index];\n          value = collection[key];\n\n          last = lastOrder.shift(value);\n\n          if (last) {\n            // if we have already seen this object, then we need to reuse the\n            // associated scope/element\n            childScope = last.scope;\n            nextOrder.push(value, last);\n\n            if (index === last.index) {\n              // do nothing\n              cursor = last.element;\n            } else {\n              // existing item which got moved\n              last.index = index;\n              // This may be a noop, if the element is next, but I don't know of a good way to\n              // figure this out,  since it would require extra DOM access, so let's just hope that\n              // the browsers realizes that it is noop, and treats it as such.\n              cursor.after(last.element);\n              cursor = last.element;\n            }\n          } else {\n            // new item which we don't know about\n            childScope = scope.$new();\n          }\n\n          childScope[valueIdent] = value;\n          if (keyIdent) childScope[keyIdent] = key;\n          childScope.$index = index;\n\n          childScope.$first = (index === 0);\n          childScope.$last = (index === (arrayLength - 1));\n          childScope.$middle = !(childScope.$first || childScope.$last);\n\n          if (!last) {\n            linker(childScope, function(clone){\n              cursor.after(clone);\n              last = {\n                  scope: childScope,\n                  element: (cursor = clone),\n                  index: index\n                };\n              nextOrder.push(value, last);\n            });\n          }\n        }\n\n        //shrink children\n        for (key in lastOrder) {\n          if (lastOrder.hasOwnProperty(key)) {\n            array = lastOrder[key];\n            while(array.length) {\n              value = array.pop();\n              value.element.remove();\n              value.scope.$destroy();\n            }\n          }\n        }\n\n        lastOrder = nextOrder;\n      });\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngShow\n *\n * @description\n * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when your checkbox is checked.</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when your checkbox is checked.</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngShowDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n    element.css('display', toBoolean(value) ? '' : 'none');\n  });\n});\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHide\n *\n * @description\n * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)\n * conditionally.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n   <doc:example>\n     <doc:source>\n        Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        Show: <span ng-show=\"checked\">I show up when you checkbox is checked?</span> <br/>\n        Hide: <span ng-hide=\"checked\">I hide when you checkbox is checked?</span>\n     </doc:source>\n     <doc:scenario>\n       it('should check ng-show / ng-hide', function() {\n         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);\n\n         input('checked').check();\n\n         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);\n         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);\n       });\n     </doc:scenario>\n   </doc:example>\n */\n//TODO(misko): refactor to remove element from the DOM\nvar ngHideDirective = ngDirective(function(scope, element, attr){\n  scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n    element.css('display', toBoolean(value) ? 'none' : '');\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngStyle\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle {@link guide/expression Expression} which evals to an\n *      object whose keys are CSS style names and values are corresponding values for those CSS\n *      keys.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"scenario.js\">\n       it('should check ng-style', function() {\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n         element('.doc-example-live :button[value=set]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');\n         element('.doc-example-live :button[value=clear]').click();\n         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSwitch\n * @restrict EA\n *\n * @description\n * Conditionally change the DOM structure.\n *\n * @usageContent\n * <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   ...\n *   <ANY ng-switch-default>...</ANY>\n *\n * @scope\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * @paramDescription\n * On child elments add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed.\n * * `ngSwitchDefault`: the default case when no other casses match.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n          function Ctrl($scope) {\n            $scope.items = ['settings', 'home', 'other'];\n            $scope.selection = $scope.items[0];\n          }\n        </script>\n        <div ng-controller=\"Ctrl\">\n          <select ng-model=\"selection\" ng-options=\"item for item in items\">\n          </select>\n          <tt>selection={{selection}}</tt>\n          <hr/>\n          <div ng-switch on=\"selection\" >\n            <div ng-switch-when=\"settings\">Settings Div</div>\n            <span ng-switch-when=\"home\">Home Span</span>\n            <span ng-switch-default>default</span>\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n        it('should start in settings', function() {\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);\n        });\n        it('should change to home', function() {\n         select('selection').option('home');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);\n        });\n        it('should select deafault', function() {\n         select('selection').option('other');\n         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);\n        });\n      </doc:scenario>\n    </doc:example>\n */\nvar NG_SWITCH = 'ng-switch';\nvar ngSwitchDirective = valueFn({\n  restrict: 'EA',\n  require: 'ngSwitch',\n  // asks for $scope to fool the BC controller module\n  controller: ['$scope', function ngSwitchController() {\n    this.cases = {};\n  }],\n  link: function(scope, element, attr, ctrl) {\n    var watchExpr = attr.ngSwitch || attr.on,\n        selectedTransclude,\n        selectedElement,\n        selectedScope;\n\n    scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n      if (selectedElement) {\n        selectedScope.$destroy();\n        selectedElement.remove();\n        selectedElement = selectedScope = null;\n      }\n      if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {\n        scope.$eval(attr.change);\n        selectedScope = scope.$new();\n        selectedTransclude(selectedScope, function(caseElement) {\n          selectedElement = caseElement;\n          element.append(caseElement);\n        });\n      }\n    });\n  }\n});\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;\n    };\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 500,\n  require: '^ngSwitch',\n  compile: function(element, attrs, transclude) {\n    return function(scope, element, attr, ctrl) {\n      ctrl.cases['?'] = transclude;\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngTransclude\n *\n * @description\n * Insert the transcluded DOM here.\n *\n * @element ANY\n *\n * @example\n   <doc:example module=\"transclude\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }\n\n         angular.module('transclude', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: 'isolate',\n               locals: { title:'bind' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         });\n       </script>\n       <div ng-controller=\"Ctrl\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </doc:source>\n     <doc:scenario>\n        it('should have transcluded', function() {\n          input('title').enter('TITLE');\n          input('text').enter('TEXT');\n          expect(binding('title')).toEqual('TITLE');\n          expect(binding('text')).toEqual('TEXT');\n        });\n     </doc:scenario>\n   </doc:example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  controller: ['$transclude', '$element', function($transclude, $element) {\n    $transclude(function(clone) {\n      $element.append(clone);\n    });\n  }]\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ng.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * @scope\n * @example\n    <example module=\"ngView\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div ng-view></div>\n          <hr />\n\n          <pre>$location.path() = {{$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n      </file>\n\n      <file name=\"chapter.html\">\n        controller: {{name}}<br />\n        Book Id: {{params.bookId}}<br />\n        Chapter Id: {{params.chapterId}}\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngView', [], function($routeProvider, $locationProvider) {\n          $routeProvider.when('/Book/:bookId', {\n            templateUrl: 'book.html',\n            controller: BookCntl\n          });\n          $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n            templateUrl: 'chapter.html',\n            controller: ChapterCntl\n          });\n\n          // configure html5 to get links working on jsfiddle\n          $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($scope, $route, $routeParams, $location) {\n          $scope.$route = $route;\n          $scope.$location = $location;\n          $scope.$routeParams = $routeParams;\n        }\n\n        function BookCntl($scope, $routeParams) {\n          $scope.name = \"BookCntl\";\n          $scope.params = $routeParams;\n        }\n\n        function ChapterCntl($scope, $routeParams) {\n          $scope.name = \"ChapterCntl\";\n          $scope.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"scenario.js\">\n        it('should load and compile correct template', function() {\n          element('a:contains(\"Moby: Ch1\")').click();\n          var content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element('a:contains(\"Scarlet\")').click();\n          content = element('.doc-example-live [ng-view]').text();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ng.directive:ngView#$viewContentLoaded\n * @eventOf ng.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nvar ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile',\n                       '$controller',\n               function($http,   $templateCache,   $route,   $anchorScroll,   $compile,\n                        $controller) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    link: function(scope, element, attr) {\n      var lastScope,\n          onloadExp = attr.onload || '';\n\n      scope.$on('$routeChangeSuccess', update);\n      update();\n\n\n      function destroyLastScope() {\n        if (lastScope) {\n          lastScope.$destroy();\n          lastScope = null;\n        }\n      }\n\n      function clearContent() {\n        element.html('');\n        destroyLastScope();\n      }\n\n      function update() {\n        var locals = $route.current && $route.current.locals,\n            template = locals && locals.$template;\n\n        if (template) {\n          element.html(template);\n          destroyLastScope();\n\n          var link = $compile(element.contents()),\n              current = $route.current,\n              controller;\n\n          lastScope = current.scope = scope.$new();\n          if (current.controller) {\n            locals.$scope = lastScope;\n            controller = $controller(current.controller, locals);\n            element.children().data('$ngControllerController', controller);\n          }\n\n          link(lastScope);\n          lastScope.$emit('$viewContentLoaded');\n          lastScope.$eval(onloadExp);\n\n          // $anchorScroll might listen on event...\n          $anchorScroll();\n        } else {\n          clearContent();\n        }\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:script\n *\n * @description\n * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the\n * template can be used by `ngInclude`, `ngView` or directive templates.\n *\n * @restrict E\n * @param {'text/ng-template'} type must be set to `'text/ng-template'`\n *\n * @example\n  <doc:example>\n    <doc:source>\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </doc:source>\n    <doc:scenario>\n      it('should load template defined inside script tag', function() {\n        element('#tpl-link').click();\n        expect(element('#tpl-content').text()).toMatch(/Content of the template/);\n      });\n    </doc:scenario>\n  </doc:example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ng.directive:select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for a `<select>` element using an array or an object obtained by evaluating the\n * `ngOptions` expression.\n *˝˝\n * When an item in the select menu is select, the value of array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive of the parent select element.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can currently\n * be bound to string values only.\n *\n * @param {string} name assignable expression to data-bind to.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *\n * @example\n    <doc:example>\n      <doc:source>\n        <script>\n        function MyCntrl($scope) {\n          $scope.colors = [\n            {name:'black', shade:'dark'},\n            {name:'white', shade:'light'},\n            {name:'red', shade:'dark'},\n            {name:'blue', shade:'dark'},\n            {name:'yellow', shade:'light'}\n          ];\n          $scope.color = $scope.colors[2]; // red\n        }\n        </script>\n        <div ng-controller=\"MyCntrl\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"color\" ng-options=\"c.name for c in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"color\" ng-options=\"c.name for c in colors\">\n              <option value=\"\">-- chose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"color\" ng-options=\"c.name group by c.shade for c in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"color={name:'not in list'}\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:color}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':color.name}\">\n          </div>\n        </div>\n      </doc:source>\n      <doc:scenario>\n         it('should check ng-options', function() {\n           expect(binding('{selected_color:color}')).toMatch('red');\n           select('color').option('0');\n           expect(binding('{selected_color:color}')).toMatch('black');\n           using('.nullable').select('color').option('');\n           expect(binding('{selected_color:color}')).toMatch('null');\n         });\n      </doc:scenario>\n    </doc:example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777\n  var NG_OPTIONS_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*)|(?:\\(\\s*([\\$\\w][\\$\\w\\d]*)\\s*,\\s*([\\$\\w][\\$\\w\\d]*)\\s*\\)))\\s+in\\s+(.*)$/,\n      nullModelCtrl = {$setViewValue: noop};\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      }\n\n\n      self.addOption = function(value) {\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      }\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      }\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value == '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple && (attr.required || attr.ngRequired)) {\n        var requiredValidator = function(value) {\n          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));\n          return value;\n        };\n\n        ngModelCtrl.$parsers.push(requiredValidator);\n        ngModelCtrl.$formatters.unshift(requiredValidator);\n\n        attr.$observe('required', function() {\n          requiredValidator(ngModelCtrl.$viewValue);\n        });\n      }\n\n      if (optionsExp) Options(scope, element, ngModelCtrl);\n      else if (multiple) Multiple(scope, element, ngModelCtrl);\n      else Single(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function Single(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function Multiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = copy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function Options(scope, selectElement, ctrl) {\n        var match;\n\n        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw Error(\n            \"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '\" + optionsExp + \"'.\");\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            // This is an array of array of existing option groups in DOM. We try to reuse these if possible\n            // optionGroupsCache[0] is the options with no option group\n            // optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.html('') because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.html('');\n\n        selectElement.bind('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    locals[valueName] = collection[key];\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key == ''){\n                value = null;\n              } else {\n                locals[valueName] = collection[key];\n                if (keyName) locals[keyName] = key;\n                value = valueFn(scope, locals);\n              }\n            }\n            ctrl.$setViewValue(value);\n          });\n        });\n\n        ctrl.$render = render;\n\n        // TODO(vojta): can't we optimize this ?\n        scope.$watch(render);\n\n        function render() {\n          var optionGroups = {'':[]}, // Temporary location for the option groups before we render them\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = false, // nothing is selected yet\n              lastElement,\n              element,\n              label;\n\n          if (multiple) {\n            selectedSet = new HashMap(modelValue);\n          } else if (modelValue === null || nullOption) {\n            // if we are not multiselect, and we are null then we have to add the nullOption\n            optionGroups[''].push({selected:modelValue === null, id:'', label:''});\n            selectedSet = true;\n          }\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n               locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];\n               optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;\n            } else {\n              selected = modelValue === valueFn(scope, locals);\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n            label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values\n            optionGroup.push({\n              id: keyName ? keys[index] : index,   // either the index into array or key from object\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple && !selectedSet) {\n            // nothing was selected, we have to insert the undefined item\n            optionGroups[''].unshift({id:'?', label:'', selected:true});\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                if (existingOption.element.selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .attr('selected', option.selected)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              existingOptions.pop().element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  }\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.bind('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  }\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\nangular.element(document).find('head').append('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "chapter9/recipe1/contacts/vendor/assets/javascripts/underscore.js",
    "content": "//     Underscore.js 1.4.4\n//     http://underscorejs.org\n//     (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.\n//     Underscore may be freely distributed under the MIT license.\n\n(function() {\n\n  // Baseline setup\n  // --------------\n\n  // Establish the root object, `window` in the browser, or `global` on the server.\n  var root = this;\n\n  // Save the previous value of the `_` variable.\n  var previousUnderscore = root._;\n\n  // Establish the object that gets returned to break out of a loop iteration.\n  var breaker = {};\n\n  // Save bytes in the minified (but not gzipped) version:\n  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;\n\n  // Create quick reference variables for speed access to core prototypes.\n  var push             = ArrayProto.push,\n      slice            = ArrayProto.slice,\n      concat           = ArrayProto.concat,\n      toString         = ObjProto.toString,\n      hasOwnProperty   = ObjProto.hasOwnProperty;\n\n  // All **ECMAScript 5** native function implementations that we hope to use\n  // are declared here.\n  var\n    nativeForEach      = ArrayProto.forEach,\n    nativeMap          = ArrayProto.map,\n    nativeReduce       = ArrayProto.reduce,\n    nativeReduceRight  = ArrayProto.reduceRight,\n    nativeFilter       = ArrayProto.filter,\n    nativeEvery        = ArrayProto.every,\n    nativeSome         = ArrayProto.some,\n    nativeIndexOf      = ArrayProto.indexOf,\n    nativeLastIndexOf  = ArrayProto.lastIndexOf,\n    nativeIsArray      = Array.isArray,\n    nativeKeys         = Object.keys,\n    nativeBind         = FuncProto.bind;\n\n  // Create a safe reference to the Underscore object for use below.\n  var _ = function(obj) {\n    if (obj instanceof _) return obj;\n    if (!(this instanceof _)) return new _(obj);\n    this._wrapped = obj;\n  };\n\n  // Export the Underscore object for **Node.js**, with\n  // backwards-compatibility for the old `require()` API. If we're in\n  // the browser, add `_` as a global object via a string identifier,\n  // for Closure Compiler \"advanced\" mode.\n  if (typeof exports !== 'undefined') {\n    if (typeof module !== 'undefined' && module.exports) {\n      exports = module.exports = _;\n    }\n    exports._ = _;\n  } else {\n    root._ = _;\n  }\n\n  // Current version.\n  _.VERSION = '1.4.4';\n\n  // Collection Functions\n  // --------------------\n\n  // The cornerstone, an `each` implementation, aka `forEach`.\n  // Handles objects with the built-in `forEach`, arrays, and raw objects.\n  // Delegates to **ECMAScript 5**'s native `forEach` if available.\n  var each = _.each = _.forEach = function(obj, iterator, context) {\n    if (obj == null) return;\n    if (nativeForEach && obj.forEach === nativeForEach) {\n      obj.forEach(iterator, context);\n    } else if (obj.length === +obj.length) {\n      for (var i = 0, l = obj.length; i < l; i++) {\n        if (iterator.call(context, obj[i], i, obj) === breaker) return;\n      }\n    } else {\n      for (var key in obj) {\n        if (_.has(obj, key)) {\n          if (iterator.call(context, obj[key], key, obj) === breaker) return;\n        }\n      }\n    }\n  };\n\n  // Return the results of applying the iterator to each element.\n  // Delegates to **ECMAScript 5**'s native `map` if available.\n  _.map = _.collect = function(obj, iterator, context) {\n    var results = [];\n    if (obj == null) return results;\n    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);\n    each(obj, function(value, index, list) {\n      results[results.length] = iterator.call(context, value, index, list);\n    });\n    return results;\n  };\n\n  var reduceError = 'Reduce of empty array with no initial value';\n\n  // **Reduce** builds up a single result from a list of values, aka `inject`,\n  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.\n  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {\n    var initial = arguments.length > 2;\n    if (obj == null) obj = [];\n    if (nativeReduce && obj.reduce === nativeReduce) {\n      if (context) iterator = _.bind(iterator, context);\n      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);\n    }\n    each(obj, function(value, index, list) {\n      if (!initial) {\n        memo = value;\n        initial = true;\n      } else {\n        memo = iterator.call(context, memo, value, index, list);\n      }\n    });\n    if (!initial) throw new TypeError(reduceError);\n    return memo;\n  };\n\n  // The right-associative version of reduce, also known as `foldr`.\n  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.\n  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {\n    var initial = arguments.length > 2;\n    if (obj == null) obj = [];\n    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {\n      if (context) iterator = _.bind(iterator, context);\n      return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);\n    }\n    var length = obj.length;\n    if (length !== +length) {\n      var keys = _.keys(obj);\n      length = keys.length;\n    }\n    each(obj, function(value, index, list) {\n      index = keys ? keys[--length] : --length;\n      if (!initial) {\n        memo = obj[index];\n        initial = true;\n      } else {\n        memo = iterator.call(context, memo, obj[index], index, list);\n      }\n    });\n    if (!initial) throw new TypeError(reduceError);\n    return memo;\n  };\n\n  // Return the first value which passes a truth test. Aliased as `detect`.\n  _.find = _.detect = function(obj, iterator, context) {\n    var result;\n    any(obj, function(value, index, list) {\n      if (iterator.call(context, value, index, list)) {\n        result = value;\n        return true;\n      }\n    });\n    return result;\n  };\n\n  // Return all the elements that pass a truth test.\n  // Delegates to **ECMAScript 5**'s native `filter` if available.\n  // Aliased as `select`.\n  _.filter = _.select = function(obj, iterator, context) {\n    var results = [];\n    if (obj == null) return results;\n    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);\n    each(obj, function(value, index, list) {\n      if (iterator.call(context, value, index, list)) results[results.length] = value;\n    });\n    return results;\n  };\n\n  // Return all the elements for which a truth test fails.\n  _.reject = function(obj, iterator, context) {\n    return _.filter(obj, function(value, index, list) {\n      return !iterator.call(context, value, index, list);\n    }, context);\n  };\n\n  // Determine whether all of the elements match a truth test.\n  // Delegates to **ECMAScript 5**'s native `every` if available.\n  // Aliased as `all`.\n  _.every = _.all = function(obj, iterator, context) {\n    iterator || (iterator = _.identity);\n    var result = true;\n    if (obj == null) return result;\n    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);\n    each(obj, function(value, index, list) {\n      if (!(result = result && iterator.call(context, value, index, list))) return breaker;\n    });\n    return !!result;\n  };\n\n  // Determine if at least one element in the object matches a truth test.\n  // Delegates to **ECMAScript 5**'s native `some` if available.\n  // Aliased as `any`.\n  var any = _.some = _.any = function(obj, iterator, context) {\n    iterator || (iterator = _.identity);\n    var result = false;\n    if (obj == null) return result;\n    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);\n    each(obj, function(value, index, list) {\n      if (result || (result = iterator.call(context, value, index, list))) return breaker;\n    });\n    return !!result;\n  };\n\n  // Determine if the array or object contains a given value (using `===`).\n  // Aliased as `include`.\n  _.contains = _.include = function(obj, target) {\n    if (obj == null) return false;\n    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;\n    return any(obj, function(value) {\n      return value === target;\n    });\n  };\n\n  // Invoke a method (with arguments) on every item in a collection.\n  _.invoke = function(obj, method) {\n    var args = slice.call(arguments, 2);\n    var isFunc = _.isFunction(method);\n    return _.map(obj, function(value) {\n      return (isFunc ? method : value[method]).apply(value, args);\n    });\n  };\n\n  // Convenience version of a common use case of `map`: fetching a property.\n  _.pluck = function(obj, key) {\n    return _.map(obj, function(value){ return value[key]; });\n  };\n\n  // Convenience version of a common use case of `filter`: selecting only objects\n  // containing specific `key:value` pairs.\n  _.where = function(obj, attrs, first) {\n    if (_.isEmpty(attrs)) return first ? null : [];\n    return _[first ? 'find' : 'filter'](obj, function(value) {\n      for (var key in attrs) {\n        if (attrs[key] !== value[key]) return false;\n      }\n      return true;\n    });\n  };\n\n  // Convenience version of a common use case of `find`: getting the first object\n  // containing specific `key:value` pairs.\n  _.findWhere = function(obj, attrs) {\n    return _.where(obj, attrs, true);\n  };\n\n  // Return the maximum element or (element-based computation).\n  // Can't optimize arrays of integers longer than 65,535 elements.\n  // See: https://bugs.webkit.org/show_bug.cgi?id=80797\n  _.max = function(obj, iterator, context) {\n    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {\n      return Math.max.apply(Math, obj);\n    }\n    if (!iterator && _.isEmpty(obj)) return -Infinity;\n    var result = {computed : -Infinity, value: -Infinity};\n    each(obj, function(value, index, list) {\n      var computed = iterator ? iterator.call(context, value, index, list) : value;\n      computed >= result.computed && (result = {value : value, computed : computed});\n    });\n    return result.value;\n  };\n\n  // Return the minimum element (or element-based computation).\n  _.min = function(obj, iterator, context) {\n    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {\n      return Math.min.apply(Math, obj);\n    }\n    if (!iterator && _.isEmpty(obj)) return Infinity;\n    var result = {computed : Infinity, value: Infinity};\n    each(obj, function(value, index, list) {\n      var computed = iterator ? iterator.call(context, value, index, list) : value;\n      computed < result.computed && (result = {value : value, computed : computed});\n    });\n    return result.value;\n  };\n\n  // Shuffle an array.\n  _.shuffle = function(obj) {\n    var rand;\n    var index = 0;\n    var shuffled = [];\n    each(obj, function(value) {\n      rand = _.random(index++);\n      shuffled[index - 1] = shuffled[rand];\n      shuffled[rand] = value;\n    });\n    return shuffled;\n  };\n\n  // An internal function to generate lookup iterators.\n  var lookupIterator = function(value) {\n    return _.isFunction(value) ? value : function(obj){ return obj[value]; };\n  };\n\n  // Sort the object's values by a criterion produced by an iterator.\n  _.sortBy = function(obj, value, context) {\n    var iterator = lookupIterator(value);\n    return _.pluck(_.map(obj, function(value, index, list) {\n      return {\n        value : value,\n        index : index,\n        criteria : iterator.call(context, value, index, list)\n      };\n    }).sort(function(left, right) {\n      var a = left.criteria;\n      var b = right.criteria;\n      if (a !== b) {\n        if (a > b || a === void 0) return 1;\n        if (a < b || b === void 0) return -1;\n      }\n      return left.index < right.index ? -1 : 1;\n    }), 'value');\n  };\n\n  // An internal function used for aggregate \"group by\" operations.\n  var group = function(obj, value, context, behavior) {\n    var result = {};\n    var iterator = lookupIterator(value || _.identity);\n    each(obj, function(value, index) {\n      var key = iterator.call(context, value, index, obj);\n      behavior(result, key, value);\n    });\n    return result;\n  };\n\n  // Groups the object's values by a criterion. Pass either a string attribute\n  // to group by, or a function that returns the criterion.\n  _.groupBy = function(obj, value, context) {\n    return group(obj, value, context, function(result, key, value) {\n      (_.has(result, key) ? result[key] : (result[key] = [])).push(value);\n    });\n  };\n\n  // Counts instances of an object that group by a certain criterion. Pass\n  // either a string attribute to count by, or a function that returns the\n  // criterion.\n  _.countBy = function(obj, value, context) {\n    return group(obj, value, context, function(result, key) {\n      if (!_.has(result, key)) result[key] = 0;\n      result[key]++;\n    });\n  };\n\n  // Use a comparator function to figure out the smallest index at which\n  // an object should be inserted so as to maintain order. Uses binary search.\n  _.sortedIndex = function(array, obj, iterator, context) {\n    iterator = iterator == null ? _.identity : lookupIterator(iterator);\n    var value = iterator.call(context, obj);\n    var low = 0, high = array.length;\n    while (low < high) {\n      var mid = (low + high) >>> 1;\n      iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;\n    }\n    return low;\n  };\n\n  // Safely convert anything iterable into a real, live array.\n  _.toArray = function(obj) {\n    if (!obj) return [];\n    if (_.isArray(obj)) return slice.call(obj);\n    if (obj.length === +obj.length) return _.map(obj, _.identity);\n    return _.values(obj);\n  };\n\n  // Return the number of elements in an object.\n  _.size = function(obj) {\n    if (obj == null) return 0;\n    return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;\n  };\n\n  // Array Functions\n  // ---------------\n\n  // Get the first element of an array. Passing **n** will return the first N\n  // values in the array. Aliased as `head` and `take`. The **guard** check\n  // allows it to work with `_.map`.\n  _.first = _.head = _.take = function(array, n, guard) {\n    if (array == null) return void 0;\n    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];\n  };\n\n  // Returns everything but the last entry of the array. Especially useful on\n  // the arguments object. Passing **n** will return all the values in\n  // the array, excluding the last N. The **guard** check allows it to work with\n  // `_.map`.\n  _.initial = function(array, n, guard) {\n    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));\n  };\n\n  // Get the last element of an array. Passing **n** will return the last N\n  // values in the array. The **guard** check allows it to work with `_.map`.\n  _.last = function(array, n, guard) {\n    if (array == null) return void 0;\n    if ((n != null) && !guard) {\n      return slice.call(array, Math.max(array.length - n, 0));\n    } else {\n      return array[array.length - 1];\n    }\n  };\n\n  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.\n  // Especially useful on the arguments object. Passing an **n** will return\n  // the rest N values in the array. The **guard**\n  // check allows it to work with `_.map`.\n  _.rest = _.tail = _.drop = function(array, n, guard) {\n    return slice.call(array, (n == null) || guard ? 1 : n);\n  };\n\n  // Trim out all falsy values from an array.\n  _.compact = function(array) {\n    return _.filter(array, _.identity);\n  };\n\n  // Internal implementation of a recursive `flatten` function.\n  var flatten = function(input, shallow, output) {\n    each(input, function(value) {\n      if (_.isArray(value)) {\n        shallow ? push.apply(output, value) : flatten(value, shallow, output);\n      } else {\n        output.push(value);\n      }\n    });\n    return output;\n  };\n\n  // Return a completely flattened version of an array.\n  _.flatten = function(array, shallow) {\n    return flatten(array, shallow, []);\n  };\n\n  // Return a version of the array that does not contain the specified value(s).\n  _.without = function(array) {\n    return _.difference(array, slice.call(arguments, 1));\n  };\n\n  // Produce a duplicate-free version of the array. If the array has already\n  // been sorted, you have the option of using a faster algorithm.\n  // Aliased as `unique`.\n  _.uniq = _.unique = function(array, isSorted, iterator, context) {\n    if (_.isFunction(isSorted)) {\n      context = iterator;\n      iterator = isSorted;\n      isSorted = false;\n    }\n    var initial = iterator ? _.map(array, iterator, context) : array;\n    var results = [];\n    var seen = [];\n    each(initial, function(value, index) {\n      if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {\n        seen.push(value);\n        results.push(array[index]);\n      }\n    });\n    return results;\n  };\n\n  // Produce an array that contains the union: each distinct element from all of\n  // the passed-in arrays.\n  _.union = function() {\n    return _.uniq(concat.apply(ArrayProto, arguments));\n  };\n\n  // Produce an array that contains every item shared between all the\n  // passed-in arrays.\n  _.intersection = function(array) {\n    var rest = slice.call(arguments, 1);\n    return _.filter(_.uniq(array), function(item) {\n      return _.every(rest, function(other) {\n        return _.indexOf(other, item) >= 0;\n      });\n    });\n  };\n\n  // Take the difference between one array and a number of other arrays.\n  // Only the elements present in just the first array will remain.\n  _.difference = function(array) {\n    var rest = concat.apply(ArrayProto, slice.call(arguments, 1));\n    return _.filter(array, function(value){ return !_.contains(rest, value); });\n  };\n\n  // Zip together multiple lists into a single array -- elements that share\n  // an index go together.\n  _.zip = function() {\n    var args = slice.call(arguments);\n    var length = _.max(_.pluck(args, 'length'));\n    var results = new Array(length);\n    for (var i = 0; i < length; i++) {\n      results[i] = _.pluck(args, \"\" + i);\n    }\n    return results;\n  };\n\n  // Converts lists into objects. Pass either a single array of `[key, value]`\n  // pairs, or two parallel arrays of the same length -- one of keys, and one of\n  // the corresponding values.\n  _.object = function(list, values) {\n    if (list == null) return {};\n    var result = {};\n    for (var i = 0, l = list.length; i < l; i++) {\n      if (values) {\n        result[list[i]] = values[i];\n      } else {\n        result[list[i][0]] = list[i][1];\n      }\n    }\n    return result;\n  };\n\n  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),\n  // we need this function. Return the position of the first occurrence of an\n  // item in an array, or -1 if the item is not included in the array.\n  // Delegates to **ECMAScript 5**'s native `indexOf` if available.\n  // If the array is large and already in sort order, pass `true`\n  // for **isSorted** to use binary search.\n  _.indexOf = function(array, item, isSorted) {\n    if (array == null) return -1;\n    var i = 0, l = array.length;\n    if (isSorted) {\n      if (typeof isSorted == 'number') {\n        i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);\n      } else {\n        i = _.sortedIndex(array, item);\n        return array[i] === item ? i : -1;\n      }\n    }\n    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);\n    for (; i < l; i++) if (array[i] === item) return i;\n    return -1;\n  };\n\n  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.\n  _.lastIndexOf = function(array, item, from) {\n    if (array == null) return -1;\n    var hasIndex = from != null;\n    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {\n      return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);\n    }\n    var i = (hasIndex ? from : array.length);\n    while (i--) if (array[i] === item) return i;\n    return -1;\n  };\n\n  // Generate an integer Array containing an arithmetic progression. A port of\n  // the native Python `range()` function. See\n  // [the Python documentation](http://docs.python.org/library/functions.html#range).\n  _.range = function(start, stop, step) {\n    if (arguments.length <= 1) {\n      stop = start || 0;\n      start = 0;\n    }\n    step = arguments[2] || 1;\n\n    var len = Math.max(Math.ceil((stop - start) / step), 0);\n    var idx = 0;\n    var range = new Array(len);\n\n    while(idx < len) {\n      range[idx++] = start;\n      start += step;\n    }\n\n    return range;\n  };\n\n  // Function (ahem) Functions\n  // ------------------\n\n  // Create a function bound to a given object (assigning `this`, and arguments,\n  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if\n  // available.\n  _.bind = function(func, context) {\n    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));\n    var args = slice.call(arguments, 2);\n    return function() {\n      return func.apply(context, args.concat(slice.call(arguments)));\n    };\n  };\n\n  // Partially apply a function by creating a version that has had some of its\n  // arguments pre-filled, without changing its dynamic `this` context.\n  _.partial = function(func) {\n    var args = slice.call(arguments, 1);\n    return function() {\n      return func.apply(this, args.concat(slice.call(arguments)));\n    };\n  };\n\n  // Bind all of an object's methods to that object. Useful for ensuring that\n  // all callbacks defined on an object belong to it.\n  _.bindAll = function(obj) {\n    var funcs = slice.call(arguments, 1);\n    if (funcs.length === 0) funcs = _.functions(obj);\n    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });\n    return obj;\n  };\n\n  // Memoize an expensive function by storing its results.\n  _.memoize = function(func, hasher) {\n    var memo = {};\n    hasher || (hasher = _.identity);\n    return function() {\n      var key = hasher.apply(this, arguments);\n      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));\n    };\n  };\n\n  // Delays a function for the given number of milliseconds, and then calls\n  // it with the arguments supplied.\n  _.delay = function(func, wait) {\n    var args = slice.call(arguments, 2);\n    return setTimeout(function(){ return func.apply(null, args); }, wait);\n  };\n\n  // Defers a function, scheduling it to run after the current call stack has\n  // cleared.\n  _.defer = function(func) {\n    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));\n  };\n\n  // Returns a function, that, when invoked, will only be triggered at most once\n  // during a given window of time.\n  _.throttle = function(func, wait) {\n    var context, args, timeout, result;\n    var previous = 0;\n    var later = function() {\n      previous = new Date;\n      timeout = null;\n      result = func.apply(context, args);\n    };\n    return function() {\n      var now = new Date;\n      var remaining = wait - (now - previous);\n      context = this;\n      args = arguments;\n      if (remaining <= 0) {\n        clearTimeout(timeout);\n        timeout = null;\n        previous = now;\n        result = func.apply(context, args);\n      } else if (!timeout) {\n        timeout = setTimeout(later, remaining);\n      }\n      return result;\n    };\n  };\n\n  // Returns a function, that, as long as it continues to be invoked, will not\n  // be triggered. The function will be called after it stops being called for\n  // N milliseconds. If `immediate` is passed, trigger the function on the\n  // leading edge, instead of the trailing.\n  _.debounce = function(func, wait, immediate) {\n    var timeout, result;\n    return function() {\n      var context = this, args = arguments;\n      var later = function() {\n        timeout = null;\n        if (!immediate) result = func.apply(context, args);\n      };\n      var callNow = immediate && !timeout;\n      clearTimeout(timeout);\n      timeout = setTimeout(later, wait);\n      if (callNow) result = func.apply(context, args);\n      return result;\n    };\n  };\n\n  // Returns a function that will be executed at most one time, no matter how\n  // often you call it. Useful for lazy initialization.\n  _.once = function(func) {\n    var ran = false, memo;\n    return function() {\n      if (ran) return memo;\n      ran = true;\n      memo = func.apply(this, arguments);\n      func = null;\n      return memo;\n    };\n  };\n\n  // Returns the first function passed as an argument to the second,\n  // allowing you to adjust arguments, run code before and after, and\n  // conditionally execute the original function.\n  _.wrap = function(func, wrapper) {\n    return function() {\n      var args = [func];\n      push.apply(args, arguments);\n      return wrapper.apply(this, args);\n    };\n  };\n\n  // Returns a function that is the composition of a list of functions, each\n  // consuming the return value of the function that follows.\n  _.compose = function() {\n    var funcs = arguments;\n    return function() {\n      var args = arguments;\n      for (var i = funcs.length - 1; i >= 0; i--) {\n        args = [funcs[i].apply(this, args)];\n      }\n      return args[0];\n    };\n  };\n\n  // Returns a function that will only be executed after being called N times.\n  _.after = function(times, func) {\n    if (times <= 0) return func();\n    return function() {\n      if (--times < 1) {\n        return func.apply(this, arguments);\n      }\n    };\n  };\n\n  // Object Functions\n  // ----------------\n\n  // Retrieve the names of an object's properties.\n  // Delegates to **ECMAScript 5**'s native `Object.keys`\n  _.keys = nativeKeys || function(obj) {\n    if (obj !== Object(obj)) throw new TypeError('Invalid object');\n    var keys = [];\n    for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;\n    return keys;\n  };\n\n  // Retrieve the values of an object's properties.\n  _.values = function(obj) {\n    var values = [];\n    for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);\n    return values;\n  };\n\n  // Convert an object into a list of `[key, value]` pairs.\n  _.pairs = function(obj) {\n    var pairs = [];\n    for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);\n    return pairs;\n  };\n\n  // Invert the keys and values of an object. The values must be serializable.\n  _.invert = function(obj) {\n    var result = {};\n    for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;\n    return result;\n  };\n\n  // Return a sorted list of the function names available on the object.\n  // Aliased as `methods`\n  _.functions = _.methods = function(obj) {\n    var names = [];\n    for (var key in obj) {\n      if (_.isFunction(obj[key])) names.push(key);\n    }\n    return names.sort();\n  };\n\n  // Extend a given object with all the properties in passed-in object(s).\n  _.extend = function(obj) {\n    each(slice.call(arguments, 1), function(source) {\n      if (source) {\n        for (var prop in source) {\n          obj[prop] = source[prop];\n        }\n      }\n    });\n    return obj;\n  };\n\n  // Return a copy of the object only containing the whitelisted properties.\n  _.pick = function(obj) {\n    var copy = {};\n    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));\n    each(keys, function(key) {\n      if (key in obj) copy[key] = obj[key];\n    });\n    return copy;\n  };\n\n   // Return a copy of the object without the blacklisted properties.\n  _.omit = function(obj) {\n    var copy = {};\n    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));\n    for (var key in obj) {\n      if (!_.contains(keys, key)) copy[key] = obj[key];\n    }\n    return copy;\n  };\n\n  // Fill in a given object with default properties.\n  _.defaults = function(obj) {\n    each(slice.call(arguments, 1), function(source) {\n      if (source) {\n        for (var prop in source) {\n          if (obj[prop] == null) obj[prop] = source[prop];\n        }\n      }\n    });\n    return obj;\n  };\n\n  // Create a (shallow-cloned) duplicate of an object.\n  _.clone = function(obj) {\n    if (!_.isObject(obj)) return obj;\n    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);\n  };\n\n  // Invokes interceptor with the obj, and then returns obj.\n  // The primary purpose of this method is to \"tap into\" a method chain, in\n  // order to perform operations on intermediate results within the chain.\n  _.tap = function(obj, interceptor) {\n    interceptor(obj);\n    return obj;\n  };\n\n  // Internal recursive comparison function for `isEqual`.\n  var eq = function(a, b, aStack, bStack) {\n    // Identical objects are equal. `0 === -0`, but they aren't identical.\n    // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.\n    if (a === b) return a !== 0 || 1 / a == 1 / b;\n    // A strict comparison is necessary because `null == undefined`.\n    if (a == null || b == null) return a === b;\n    // Unwrap any wrapped objects.\n    if (a instanceof _) a = a._wrapped;\n    if (b instanceof _) b = b._wrapped;\n    // Compare `[[Class]]` names.\n    var className = toString.call(a);\n    if (className != toString.call(b)) return false;\n    switch (className) {\n      // Strings, numbers, dates, and booleans are compared by value.\n      case '[object String]':\n        // Primitives and their corresponding object wrappers are equivalent; thus, `\"5\"` is\n        // equivalent to `new String(\"5\")`.\n        return a == String(b);\n      case '[object Number]':\n        // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for\n        // other numeric values.\n        return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);\n      case '[object Date]':\n      case '[object Boolean]':\n        // Coerce dates and booleans to numeric primitive values. Dates are compared by their\n        // millisecond representations. Note that invalid dates with millisecond representations\n        // of `NaN` are not equivalent.\n        return +a == +b;\n      // RegExps are compared by their source patterns and flags.\n      case '[object RegExp]':\n        return a.source == b.source &&\n               a.global == b.global &&\n               a.multiline == b.multiline &&\n               a.ignoreCase == b.ignoreCase;\n    }\n    if (typeof a != 'object' || typeof b != 'object') return false;\n    // Assume equality for cyclic structures. The algorithm for detecting cyclic\n    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.\n    var length = aStack.length;\n    while (length--) {\n      // Linear search. Performance is inversely proportional to the number of\n      // unique nested structures.\n      if (aStack[length] == a) return bStack[length] == b;\n    }\n    // Add the first object to the stack of traversed objects.\n    aStack.push(a);\n    bStack.push(b);\n    var size = 0, result = true;\n    // Recursively compare objects and arrays.\n    if (className == '[object Array]') {\n      // Compare array lengths to determine if a deep comparison is necessary.\n      size = a.length;\n      result = size == b.length;\n      if (result) {\n        // Deep compare the contents, ignoring non-numeric properties.\n        while (size--) {\n          if (!(result = eq(a[size], b[size], aStack, bStack))) break;\n        }\n      }\n    } else {\n      // Objects with different constructors are not equivalent, but `Object`s\n      // from different frames are.\n      var aCtor = a.constructor, bCtor = b.constructor;\n      if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&\n                               _.isFunction(bCtor) && (bCtor instanceof bCtor))) {\n        return false;\n      }\n      // Deep compare objects.\n      for (var key in a) {\n        if (_.has(a, key)) {\n          // Count the expected number of properties.\n          size++;\n          // Deep compare each member.\n          if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;\n        }\n      }\n      // Ensure that both objects contain the same number of properties.\n      if (result) {\n        for (key in b) {\n          if (_.has(b, key) && !(size--)) break;\n        }\n        result = !size;\n      }\n    }\n    // Remove the first object from the stack of traversed objects.\n    aStack.pop();\n    bStack.pop();\n    return result;\n  };\n\n  // Perform a deep comparison to check if two objects are equal.\n  _.isEqual = function(a, b) {\n    return eq(a, b, [], []);\n  };\n\n  // Is a given array, string, or object empty?\n  // An \"empty\" object has no enumerable own-properties.\n  _.isEmpty = function(obj) {\n    if (obj == null) return true;\n    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;\n    for (var key in obj) if (_.has(obj, key)) return false;\n    return true;\n  };\n\n  // Is a given value a DOM element?\n  _.isElement = function(obj) {\n    return !!(obj && obj.nodeType === 1);\n  };\n\n  // Is a given value an array?\n  // Delegates to ECMA5's native Array.isArray\n  _.isArray = nativeIsArray || function(obj) {\n    return toString.call(obj) == '[object Array]';\n  };\n\n  // Is a given variable an object?\n  _.isObject = function(obj) {\n    return obj === Object(obj);\n  };\n\n  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.\n  each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {\n    _['is' + name] = function(obj) {\n      return toString.call(obj) == '[object ' + name + ']';\n    };\n  });\n\n  // Define a fallback version of the method in browsers (ahem, IE), where\n  // there isn't any inspectable \"Arguments\" type.\n  if (!_.isArguments(arguments)) {\n    _.isArguments = function(obj) {\n      return !!(obj && _.has(obj, 'callee'));\n    };\n  }\n\n  // Optimize `isFunction` if appropriate.\n  if (typeof (/./) !== 'function') {\n    _.isFunction = function(obj) {\n      return typeof obj === 'function';\n    };\n  }\n\n  // Is a given object a finite number?\n  _.isFinite = function(obj) {\n    return isFinite(obj) && !isNaN(parseFloat(obj));\n  };\n\n  // Is the given value `NaN`? (NaN is the only number which does not equal itself).\n  _.isNaN = function(obj) {\n    return _.isNumber(obj) && obj != +obj;\n  };\n\n  // Is a given value a boolean?\n  _.isBoolean = function(obj) {\n    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';\n  };\n\n  // Is a given value equal to null?\n  _.isNull = function(obj) {\n    return obj === null;\n  };\n\n  // Is a given variable undefined?\n  _.isUndefined = function(obj) {\n    return obj === void 0;\n  };\n\n  // Shortcut function for checking if an object has a given property directly\n  // on itself (in other words, not on a prototype).\n  _.has = function(obj, key) {\n    return hasOwnProperty.call(obj, key);\n  };\n\n  // Utility Functions\n  // -----------------\n\n  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its\n  // previous owner. Returns a reference to the Underscore object.\n  _.noConflict = function() {\n    root._ = previousUnderscore;\n    return this;\n  };\n\n  // Keep the identity function around for default iterators.\n  _.identity = function(value) {\n    return value;\n  };\n\n  // Run a function **n** times.\n  _.times = function(n, iterator, context) {\n    var accum = Array(n);\n    for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);\n    return accum;\n  };\n\n  // Return a random integer between min and max (inclusive).\n  _.random = function(min, max) {\n    if (max == null) {\n      max = min;\n      min = 0;\n    }\n    return min + Math.floor(Math.random() * (max - min + 1));\n  };\n\n  // List of HTML entities for escaping.\n  var entityMap = {\n    escape: {\n      '&': '&amp;',\n      '<': '&lt;',\n      '>': '&gt;',\n      '\"': '&quot;',\n      \"'\": '&#x27;',\n      '/': '&#x2F;'\n    }\n  };\n  entityMap.unescape = _.invert(entityMap.escape);\n\n  // Regexes containing the keys and values listed immediately above.\n  var entityRegexes = {\n    escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),\n    unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')\n  };\n\n  // Functions for escaping and unescaping strings to/from HTML interpolation.\n  _.each(['escape', 'unescape'], function(method) {\n    _[method] = function(string) {\n      if (string == null) return '';\n      return ('' + string).replace(entityRegexes[method], function(match) {\n        return entityMap[method][match];\n      });\n    };\n  });\n\n  // If the value of the named property is a function then invoke it;\n  // otherwise, return it.\n  _.result = function(object, property) {\n    if (object == null) return null;\n    var value = object[property];\n    return _.isFunction(value) ? value.call(object) : value;\n  };\n\n  // Add your own custom functions to the Underscore object.\n  _.mixin = function(obj) {\n    each(_.functions(obj), function(name){\n      var func = _[name] = obj[name];\n      _.prototype[name] = function() {\n        var args = [this._wrapped];\n        push.apply(args, arguments);\n        return result.call(this, func.apply(_, args));\n      };\n    });\n  };\n\n  // Generate a unique integer id (unique within the entire client session).\n  // Useful for temporary DOM ids.\n  var idCounter = 0;\n  _.uniqueId = function(prefix) {\n    var id = ++idCounter + '';\n    return prefix ? prefix + id : id;\n  };\n\n  // By default, Underscore uses ERB-style template delimiters, change the\n  // following template settings to use alternative delimiters.\n  _.templateSettings = {\n    evaluate    : /<%([\\s\\S]+?)%>/g,\n    interpolate : /<%=([\\s\\S]+?)%>/g,\n    escape      : /<%-([\\s\\S]+?)%>/g\n  };\n\n  // When customizing `templateSettings`, if you don't want to define an\n  // interpolation, evaluation or escaping regex, we need one that is\n  // guaranteed not to match.\n  var noMatch = /(.)^/;\n\n  // Certain characters need to be escaped so that they can be put into a\n  // string literal.\n  var escapes = {\n    \"'\":      \"'\",\n    '\\\\':     '\\\\',\n    '\\r':     'r',\n    '\\n':     'n',\n    '\\t':     't',\n    '\\u2028': 'u2028',\n    '\\u2029': 'u2029'\n  };\n\n  var escaper = /\\\\|'|\\r|\\n|\\t|\\u2028|\\u2029/g;\n\n  // JavaScript micro-templating, similar to John Resig's implementation.\n  // Underscore templating handles arbitrary delimiters, preserves whitespace,\n  // and correctly escapes quotes within interpolated code.\n  _.template = function(text, data, settings) {\n    var render;\n    settings = _.defaults({}, settings, _.templateSettings);\n\n    // Combine delimiters into one regular expression via alternation.\n    var matcher = new RegExp([\n      (settings.escape || noMatch).source,\n      (settings.interpolate || noMatch).source,\n      (settings.evaluate || noMatch).source\n    ].join('|') + '|$', 'g');\n\n    // Compile the template source, escaping string literals appropriately.\n    var index = 0;\n    var source = \"__p+='\";\n    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {\n      source += text.slice(index, offset)\n        .replace(escaper, function(match) { return '\\\\' + escapes[match]; });\n\n      if (escape) {\n        source += \"'+\\n((__t=(\" + escape + \"))==null?'':_.escape(__t))+\\n'\";\n      }\n      if (interpolate) {\n        source += \"'+\\n((__t=(\" + interpolate + \"))==null?'':__t)+\\n'\";\n      }\n      if (evaluate) {\n        source += \"';\\n\" + evaluate + \"\\n__p+='\";\n      }\n      index = offset + match.length;\n      return match;\n    });\n    source += \"';\\n\";\n\n    // If a variable is not specified, place data values in local scope.\n    if (!settings.variable) source = 'with(obj||{}){\\n' + source + '}\\n';\n\n    source = \"var __t,__p='',__j=Array.prototype.join,\" +\n      \"print=function(){__p+=__j.call(arguments,'');};\\n\" +\n      source + \"return __p;\\n\";\n\n    try {\n      render = new Function(settings.variable || 'obj', '_', source);\n    } catch (e) {\n      e.source = source;\n      throw e;\n    }\n\n    if (data) return render(data, _);\n    var template = function(data) {\n      return render.call(this, data, _);\n    };\n\n    // Provide the compiled function source as a convenience for precompilation.\n    template.source = 'function(' + (settings.variable || 'obj') + '){\\n' + source + '}';\n\n    return template;\n  };\n\n  // Add a \"chain\" function, which will delegate to the wrapper.\n  _.chain = function(obj) {\n    return _(obj).chain();\n  };\n\n  // OOP\n  // ---------------\n  // If Underscore is called as a function, it returns a wrapped object that\n  // can be used OO-style. This wrapper holds altered versions of all the\n  // underscore functions. Wrapped objects may be chained.\n\n  // Helper function to continue chaining intermediate results.\n  var result = function(obj) {\n    return this._chain ? _(obj).chain() : obj;\n  };\n\n  // Add all of the Underscore functions to the wrapper object.\n  _.mixin(_);\n\n  // Add all mutator Array functions to the wrapper.\n  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {\n    var method = ArrayProto[name];\n    _.prototype[name] = function() {\n      var obj = this._wrapped;\n      method.apply(obj, arguments);\n      if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];\n      return result.call(this, obj);\n    };\n  });\n\n  // Add all accessor Array functions to the wrapper.\n  each(['concat', 'join', 'slice'], function(name) {\n    var method = ArrayProto[name];\n    _.prototype[name] = function() {\n      return result.call(this, method.apply(this._wrapped, arguments));\n    };\n  });\n\n  _.extend(_.prototype, {\n\n    // Start chaining a wrapped Underscore object.\n    chain: function() {\n      this._chain = true;\n      return this;\n    },\n\n    // Extracts the result from a wrapped and chained object.\n    value: function() {\n      return this._wrapped;\n    }\n\n  });\n\n}).call(this);"
  },
  {
    "path": "chapter9/recipe1/contacts/vendor/assets/stylesheets/.gitkeep",
    "content": ""
  },
  {
    "path": "chapter9/recipe1/contacts/vendor/plugins/.gitkeep",
    "content": ""
  }
]